+ /* ---------- change page property values (48 bytes) --------------------- */
+
+ for (i = 0; i < ei->num_change_pages; i++)
+ {
+ struct ElementChangeInfo *change = &ei->change_page[i];
+ unsigned int event_bits;
+
+ /* bits 0 - 31 of "has_event[]" ... */
+ event_bits = 0;
+ for (j = 0; j < MIN(NUM_CHANGE_EVENTS, 32); j++)
+ if (change->has_event[j])
+ event_bits |= (1 << j);
+ putFile32BitBE(file, event_bits);
+
+ putFile16BitBE(file, change->target_element);
+
+ putFile16BitBE(file, change->delay_fixed);
+ putFile16BitBE(file, change->delay_random);
+ putFile16BitBE(file, change->delay_frames);
+
+ putFile16BitBE(file, change->trigger_element);
+
+ putFile8Bit(file, change->explode);
+ putFile8Bit(file, change->use_target_content);
+ putFile8Bit(file, change->only_if_complete);
+ putFile8Bit(file, change->use_random_replace);
+
+ putFile8Bit(file, change->random_percentage);
+ putFile8Bit(file, change->replace_when);
+
+ for (y = 0; y < 3; y++)
+ for (x = 0; x < 3; x++)
+ putFile16BitBE(file, change->target_content.e[x][y]);
+
+ putFile8Bit(file, change->can_change);
+
+ putFile8Bit(file, change->trigger_side);
+
+ putFile8Bit(file, change->trigger_player);
+ putFile8Bit(file, (change->trigger_page == CH_PAGE_ANY ? CH_PAGE_ANY_FILE :
+ log_2(change->trigger_page)));
+
+ putFile8Bit(file, change->has_action);
+ putFile8Bit(file, change->action_type);
+ putFile8Bit(file, change->action_mode);
+ putFile16BitBE(file, change->action_arg);
+
+ /* ... bits 32 - 39 of "has_event[]" (not nice, but downward compatible) */
+ event_bits = 0;
+ for (j = 32; j < NUM_CHANGE_EVENTS; j++)
+ if (change->has_event[j])
+ event_bits |= (1 << (j - 32));
+ putFile8Bit(file, event_bits);
+ }
+}
+
+static void SaveLevel_GRP1(FILE *file, struct LevelInfo *level, int element)
+{
+ struct ElementInfo *ei = &element_info[element];
+ struct ElementGroupInfo *group = ei->group;
+ int i;
+
+ putFile16BitBE(file, element);
+
+ for (i = 0; i < MAX_ELEMENT_NAME_LEN; i++)
+ putFile8Bit(file, ei->description[i]);
+
+ putFile8Bit(file, group->num_elements);
+
+ putFile8Bit(file, ei->use_gfx_element);
+ putFile16BitBE(file, ei->gfx_element);
+
+ putFile8Bit(file, group->choice_mode);
+
+ /* some free bytes for future values and padding */
+ WriteUnusedBytesToFile(file, 3);
+
+ for (i = 0; i < MAX_ELEMENTS_IN_GROUP; i++)
+ putFile16BitBE(file, group->element[i]);
+}
+
+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;
+}
+
+#if 0
+
+static int SaveLevel_MicroChunk_SingleValue(FILE *file,
+ struct ElementFileConfig *entry)
+{
+ 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;
+
+ /* 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 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 += 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_MicroChunk_ElementList(FILE *file,
+ struct ElementFileConfig *entry)
+{
+ 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;
+
+ /* 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;
+}
+
+static int SaveLevel_MicroChunk_ContentList(FILE *file,
+ struct ElementFileConfig *entry)
+{
+ 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;
+
+ /* 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;
+}
+
+#endif
+
+static int SaveLevel_CONF(FILE *file, struct LevelInfo *level)
+{
+ int chunk_size = 0;
+ int i;
+
+ 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;