16af2dd4b4d84769faffc1c981a4153040a98498
[rocksndiamonds.git] / src / files.c
1 // ============================================================================
2 // Rocks'n'Diamonds - McDuffin Strikes Back!
3 // ----------------------------------------------------------------------------
4 // (c) 1995-2014 by Artsoft Entertainment
5 //                  Holger Schemel
6 //                  info@artsoft.org
7 //                  http://www.artsoft.org/
8 // ----------------------------------------------------------------------------
9 // files.c
10 // ============================================================================
11
12 #include <ctype.h>
13 #include <sys/stat.h>
14 #include <dirent.h>
15 #include <math.h>
16
17 #include "libgame/libgame.h"
18
19 #include "files.h"
20 #include "init.h"
21 #include "tools.h"
22 #include "tape.h"
23
24
25 #define CHUNK_ID_LEN            4       /* IFF style chunk id length  */
26 #define CHUNK_SIZE_UNDEFINED    0       /* undefined chunk size == 0  */
27 #define CHUNK_SIZE_NONE         -1      /* do not write chunk size    */
28
29 #define LEVEL_CHUNK_NAME_SIZE   MAX_LEVEL_NAME_LEN
30 #define LEVEL_CHUNK_AUTH_SIZE   MAX_LEVEL_AUTHOR_LEN
31
32 #define LEVEL_CHUNK_VERS_SIZE   8       /* size of file version chunk */
33 #define LEVEL_CHUNK_DATE_SIZE   4       /* size of file date chunk    */
34 #define LEVEL_CHUNK_HEAD_SIZE   80      /* size of level file header  */
35 #define LEVEL_CHUNK_HEAD_UNUSED 0       /* unused level header bytes  */
36 #define LEVEL_CHUNK_CNT2_SIZE   160     /* size of level CNT2 chunk   */
37 #define LEVEL_CHUNK_CNT2_UNUSED 11      /* unused CNT2 chunk bytes    */
38 #define LEVEL_CHUNK_CNT3_HEADER 16      /* size of level CNT3 header  */
39 #define LEVEL_CHUNK_CNT3_UNUSED 10      /* unused CNT3 chunk bytes    */
40 #define LEVEL_CPART_CUS3_SIZE   134     /* size of CUS3 chunk part    */
41 #define LEVEL_CPART_CUS3_UNUSED 15      /* unused CUS3 bytes / part   */
42 #define LEVEL_CHUNK_GRP1_SIZE   74      /* size of level GRP1 chunk   */
43
44 /* (element number, number of change pages, change page number) */
45 #define LEVEL_CHUNK_CUSX_UNCHANGED      (2 + (1 + 1) + (1 + 1))
46
47 /* (element number only) */
48 #define LEVEL_CHUNK_GRPX_UNCHANGED      2
49 #define LEVEL_CHUNK_NOTE_UNCHANGED      2
50
51 /* (nothing at all if unchanged) */
52 #define LEVEL_CHUNK_ELEM_UNCHANGED      0
53
54 #define TAPE_CHUNK_VERS_SIZE    8       /* size of file version chunk */
55 #define TAPE_CHUNK_HEAD_SIZE    20      /* size of tape file header   */
56 #define TAPE_CHUNK_HEAD_UNUSED  3       /* unused tape header bytes   */
57
58 #define LEVEL_CHUNK_CNT3_SIZE(x)         (LEVEL_CHUNK_CNT3_HEADER + (x))
59 #define LEVEL_CHUNK_CUS3_SIZE(x)         (2 + (x) * LEVEL_CPART_CUS3_SIZE)
60 #define LEVEL_CHUNK_CUS4_SIZE(x)         (96 + (x) * 48)
61
62 /* file identifier strings */
63 #define LEVEL_COOKIE_TMPL               "ROCKSNDIAMONDS_LEVEL_FILE_VERSION_x.x"
64 #define TAPE_COOKIE_TMPL                "ROCKSNDIAMONDS_TAPE_FILE_VERSION_x.x"
65 #define SCORE_COOKIE                    "ROCKSNDIAMONDS_SCORE_FILE_VERSION_1.2"
66
67 /* values for deciding when (not) to save configuration data */
68 #define SAVE_CONF_NEVER                 0
69 #define SAVE_CONF_ALWAYS                1
70 #define SAVE_CONF_WHEN_CHANGED          -1
71
72 /* values for chunks using micro chunks */
73 #define CONF_MASK_1_BYTE                0x00
74 #define CONF_MASK_2_BYTE                0x40
75 #define CONF_MASK_4_BYTE                0x80
76 #define CONF_MASK_MULTI_BYTES           0xc0
77
78 #define CONF_MASK_BYTES                 0xc0
79 #define CONF_MASK_TOKEN                 0x3f
80
81 #define CONF_VALUE_1_BYTE(x)            (CONF_MASK_1_BYTE       | (x))
82 #define CONF_VALUE_2_BYTE(x)            (CONF_MASK_2_BYTE       | (x))
83 #define CONF_VALUE_4_BYTE(x)            (CONF_MASK_4_BYTE       | (x))
84 #define CONF_VALUE_MULTI_BYTES(x)       (CONF_MASK_MULTI_BYTES  | (x))
85
86 /* these definitions are just for convenience of use and readability */
87 #define CONF_VALUE_8_BIT(x)             CONF_VALUE_1_BYTE(x)
88 #define CONF_VALUE_16_BIT(x)            CONF_VALUE_2_BYTE(x)
89 #define CONF_VALUE_32_BIT(x)            CONF_VALUE_4_BYTE(x)
90 #define CONF_VALUE_BYTES(x)             CONF_VALUE_MULTI_BYTES(x)
91
92 #define CONF_VALUE_NUM_BYTES(x)         ((x) == CONF_MASK_1_BYTE ? 1 :  \
93                                          (x) == CONF_MASK_2_BYTE ? 2 :  \
94                                          (x) == CONF_MASK_4_BYTE ? 4 : 0)
95
96 #define CONF_CONTENT_NUM_ELEMENTS       (3 * 3)
97 #define CONF_CONTENT_NUM_BYTES          (CONF_CONTENT_NUM_ELEMENTS * 2)
98 #define CONF_ELEMENT_NUM_BYTES          (2)
99
100 #define CONF_ENTITY_NUM_BYTES(t)        ((t) == TYPE_ELEMENT ||         \
101                                          (t) == TYPE_ELEMENT_LIST ?     \
102                                          CONF_ELEMENT_NUM_BYTES :       \
103                                          (t) == TYPE_CONTENT ||         \
104                                          (t) == TYPE_CONTENT_LIST ?     \
105                                          CONF_CONTENT_NUM_BYTES : 1)
106
107 #define CONF_ELEMENT_BYTE_POS(i)        ((i) * CONF_ELEMENT_NUM_BYTES)
108 #define CONF_ELEMENTS_ELEMENT(b,i)     ((b[CONF_ELEMENT_BYTE_POS(i)] << 8) |  \
109                                         (b[CONF_ELEMENT_BYTE_POS(i) + 1]))
110
111 #define CONF_CONTENT_ELEMENT_POS(c,x,y) ((c) * CONF_CONTENT_NUM_ELEMENTS +    \
112                                          (y) * 3 + (x))
113 #define CONF_CONTENT_BYTE_POS(c,x,y)    (CONF_CONTENT_ELEMENT_POS(c,x,y) *    \
114                                          CONF_ELEMENT_NUM_BYTES)
115 #define CONF_CONTENTS_ELEMENT(b,c,x,y) ((b[CONF_CONTENT_BYTE_POS(c,x,y)]<< 8)|\
116                                         (b[CONF_CONTENT_BYTE_POS(c,x,y) + 1]))
117
118 /* temporary variables used to store pointers to structure members */
119 static struct LevelInfo li;
120 static struct ElementInfo xx_ei, yy_ei;
121 static struct ElementChangeInfo xx_change;
122 static struct ElementGroupInfo xx_group;
123 static struct EnvelopeInfo xx_envelope;
124 static unsigned int xx_event_bits[NUM_CE_BITFIELDS];
125 static char xx_default_description[MAX_ELEMENT_NAME_LEN + 1];
126 static int xx_num_contents;
127 static int xx_current_change_page;
128 static char xx_default_string_empty[1] = "";
129 static int xx_string_length_unused;
130
131 struct LevelFileConfigInfo
132 {
133   int element;                  /* element for which data is to be stored */
134   int save_type;                /* save data always, never or when changed */
135   int data_type;                /* data type (used internally, not stored) */
136   int conf_type;                /* micro chunk identifier (stored in file) */
137
138   /* (mandatory) */
139   void *value;                  /* variable that holds the data to be stored */
140   int default_value;            /* initial default value for this variable */
141
142   /* (optional) */
143   void *value_copy;             /* variable that holds the data to be copied */
144   void *num_entities;           /* number of entities for multi-byte data */
145   int default_num_entities;     /* default number of entities for this data */
146   int max_num_entities;         /* maximal number of entities for this data */
147   char *default_string;         /* optional default string for string data */
148 };
149
150 static struct LevelFileConfigInfo chunk_config_INFO[] =
151 {
152   /* ---------- values not related to single elements ----------------------- */
153
154   {
155     -1,                                 SAVE_CONF_ALWAYS,
156     TYPE_INTEGER,                       CONF_VALUE_8_BIT(1),
157     &li.game_engine_type,               GAME_ENGINE_TYPE_RND
158   },
159
160   {
161     -1,                                 SAVE_CONF_ALWAYS,
162     TYPE_INTEGER,                       CONF_VALUE_16_BIT(1),
163     &li.fieldx,                         STD_LEV_FIELDX
164   },
165   {
166     -1,                                 SAVE_CONF_ALWAYS,
167     TYPE_INTEGER,                       CONF_VALUE_16_BIT(2),
168     &li.fieldy,                         STD_LEV_FIELDY
169   },
170
171   {
172     -1,                                 SAVE_CONF_ALWAYS,
173     TYPE_INTEGER,                       CONF_VALUE_16_BIT(3),
174     &li.time,                           100
175   },
176
177   {
178     -1,                                 SAVE_CONF_ALWAYS,
179     TYPE_INTEGER,                       CONF_VALUE_16_BIT(4),
180     &li.gems_needed,                    0
181   },
182
183   {
184     -1,                                 -1,
185     TYPE_INTEGER,                       CONF_VALUE_32_BIT(2),
186     &li.random_seed,                    0
187   },
188
189   {
190     -1,                                 -1,
191     TYPE_BOOLEAN,                       CONF_VALUE_8_BIT(2),
192     &li.use_step_counter,               FALSE
193   },
194
195   {
196     -1,                                 -1,
197     TYPE_BITFIELD,                      CONF_VALUE_8_BIT(4),
198     &li.wind_direction_initial,         MV_NONE
199   },
200
201   {
202     -1,                                 -1,
203     TYPE_BOOLEAN,                       CONF_VALUE_8_BIT(5),
204     &li.em_slippery_gems,               FALSE
205   },
206
207   {
208     -1,                                 -1,
209     TYPE_BOOLEAN,                       CONF_VALUE_8_BIT(6),
210     &li.use_custom_template,            FALSE
211   },
212
213   {
214     -1,                                 -1,
215     TYPE_BITFIELD,                      CONF_VALUE_32_BIT(1),
216     &li.can_move_into_acid_bits,        ~0      /* default: everything can */
217   },
218
219   {
220     -1,                                 -1,
221     TYPE_BITFIELD,                      CONF_VALUE_8_BIT(7),
222     &li.dont_collide_with_bits,         ~0      /* default: always deadly */
223   },
224
225   {
226     -1,                                 -1,
227     TYPE_BOOLEAN,                       CONF_VALUE_8_BIT(8),
228     &li.em_explodes_by_fire,            FALSE
229   },
230
231   {
232     -1,                                 -1,
233     TYPE_INTEGER,                       CONF_VALUE_16_BIT(5),
234     &li.score[SC_TIME_BONUS],           1
235   },
236
237   {
238     -1,                                 -1,
239     TYPE_BOOLEAN,                       CONF_VALUE_8_BIT(9),
240     &li.auto_exit_sokoban,              FALSE
241   },
242
243   {
244     -1,                                 -1,
245     -1,                                 -1,
246     NULL,                               -1
247   }
248 };
249
250 static struct LevelFileConfigInfo chunk_config_ELEM[] =
251 {
252   /* (these values are the same for each player) */
253   {
254     EL_PLAYER_1,                        -1,
255     TYPE_BOOLEAN,                       CONF_VALUE_8_BIT(1),
256     &li.block_last_field,               FALSE   /* default case for EM levels */
257   },
258   {
259     EL_PLAYER_1,                        -1,
260     TYPE_BOOLEAN,                       CONF_VALUE_8_BIT(2),
261     &li.sp_block_last_field,            TRUE    /* default case for SP levels */
262   },
263   {
264     EL_PLAYER_1,                        -1,
265     TYPE_BOOLEAN,                       CONF_VALUE_8_BIT(3),
266     &li.instant_relocation,             FALSE
267   },
268   {
269     EL_PLAYER_1,                        -1,
270     TYPE_BOOLEAN,                       CONF_VALUE_8_BIT(4),
271     &li.can_pass_to_walkable,           FALSE
272   },
273   {
274     EL_PLAYER_1,                        -1,
275     TYPE_BOOLEAN,                       CONF_VALUE_8_BIT(5),
276     &li.block_snap_field,               TRUE
277   },
278   {
279     EL_PLAYER_1,                        -1,
280     TYPE_BOOLEAN,                       CONF_VALUE_8_BIT(6),
281     &li.continuous_snapping,            TRUE
282   },
283   {
284     EL_PLAYER_1,                        -1,
285     TYPE_BOOLEAN,                       CONF_VALUE_8_BIT(12),
286     &li.shifted_relocation,             FALSE
287   },
288
289   /* (these values are different for each player) */
290   {
291     EL_PLAYER_1,                        -1,
292     TYPE_INTEGER,                       CONF_VALUE_8_BIT(7),
293     &li.initial_player_stepsize[0],     STEPSIZE_NORMAL
294   },
295   {
296     EL_PLAYER_1,                        -1,
297     TYPE_BOOLEAN,                       CONF_VALUE_8_BIT(8),
298     &li.initial_player_gravity[0],      FALSE
299   },
300   {
301     EL_PLAYER_1,                        -1,
302     TYPE_BOOLEAN,                       CONF_VALUE_8_BIT(9),
303     &li.use_start_element[0],           FALSE
304   },
305   {
306     EL_PLAYER_1,                        -1,
307     TYPE_ELEMENT,                       CONF_VALUE_16_BIT(1),
308     &li.start_element[0],               EL_PLAYER_1
309   },
310   {
311     EL_PLAYER_1,                        -1,
312     TYPE_BOOLEAN,                       CONF_VALUE_8_BIT(10),
313     &li.use_artwork_element[0],         FALSE
314   },
315   {
316     EL_PLAYER_1,                        -1,
317     TYPE_ELEMENT,                       CONF_VALUE_16_BIT(2),
318     &li.artwork_element[0],             EL_PLAYER_1
319   },
320   {
321     EL_PLAYER_1,                        -1,
322     TYPE_BOOLEAN,                       CONF_VALUE_8_BIT(11),
323     &li.use_explosion_element[0],       FALSE
324   },
325   {
326     EL_PLAYER_1,                        -1,
327     TYPE_ELEMENT,                       CONF_VALUE_16_BIT(3),
328     &li.explosion_element[0],           EL_PLAYER_1
329   },
330   {
331     EL_PLAYER_1,                        -1,
332     TYPE_BOOLEAN,                       CONF_VALUE_8_BIT(13),
333     &li.use_initial_inventory[0],       FALSE
334   },
335   {
336     EL_PLAYER_1,                        -1,
337     TYPE_BOOLEAN,                       CONF_VALUE_8_BIT(14),
338     &li.initial_inventory_size[0],      1
339   },
340   {
341     EL_PLAYER_1,                        -1,
342     TYPE_ELEMENT_LIST,                  CONF_VALUE_BYTES(1),
343     &li.initial_inventory_content[0][0],EL_EMPTY, NULL,
344     &li.initial_inventory_size[0],      1, MAX_INITIAL_INVENTORY_SIZE
345   },
346
347   {
348     EL_PLAYER_2,                        -1,
349     TYPE_INTEGER,                       CONF_VALUE_8_BIT(7),
350     &li.initial_player_stepsize[1],     STEPSIZE_NORMAL
351   },
352   {
353     EL_PLAYER_2,                        -1,
354     TYPE_BOOLEAN,                       CONF_VALUE_8_BIT(8),
355     &li.initial_player_gravity[1],      FALSE
356   },
357   {
358     EL_PLAYER_2,                        -1,
359     TYPE_BOOLEAN,                       CONF_VALUE_8_BIT(9),
360     &li.use_start_element[1],           FALSE
361   },
362   {
363     EL_PLAYER_2,                        -1,
364     TYPE_ELEMENT,                       CONF_VALUE_16_BIT(1),
365     &li.start_element[1],               EL_PLAYER_2
366   },
367   {
368     EL_PLAYER_2,                        -1,
369     TYPE_BOOLEAN,                       CONF_VALUE_8_BIT(10),
370     &li.use_artwork_element[1],         FALSE
371   },
372   {
373     EL_PLAYER_2,                        -1,
374     TYPE_ELEMENT,                       CONF_VALUE_16_BIT(2),
375     &li.artwork_element[1],             EL_PLAYER_2
376   },
377   {
378     EL_PLAYER_2,                        -1,
379     TYPE_BOOLEAN,                       CONF_VALUE_8_BIT(11),
380     &li.use_explosion_element[1],       FALSE
381   },
382   {
383     EL_PLAYER_2,                        -1,
384     TYPE_ELEMENT,                       CONF_VALUE_16_BIT(3),
385     &li.explosion_element[1],           EL_PLAYER_2
386   },
387   {
388     EL_PLAYER_2,                        -1,
389     TYPE_BOOLEAN,                       CONF_VALUE_8_BIT(13),
390     &li.use_initial_inventory[1],       FALSE
391   },
392   {
393     EL_PLAYER_2,                        -1,
394     TYPE_BOOLEAN,                       CONF_VALUE_8_BIT(14),
395     &li.initial_inventory_size[1],      1
396   },
397   {
398     EL_PLAYER_2,                        -1,
399     TYPE_ELEMENT_LIST,                  CONF_VALUE_BYTES(1),
400     &li.initial_inventory_content[1][0],EL_EMPTY, NULL,
401     &li.initial_inventory_size[1],      1, MAX_INITIAL_INVENTORY_SIZE
402   },
403
404   {
405     EL_PLAYER_3,                        -1,
406     TYPE_INTEGER,                       CONF_VALUE_8_BIT(7),
407     &li.initial_player_stepsize[2],     STEPSIZE_NORMAL
408   },
409   {
410     EL_PLAYER_3,                        -1,
411     TYPE_BOOLEAN,                       CONF_VALUE_8_BIT(8),
412     &li.initial_player_gravity[2],      FALSE
413   },
414   {
415     EL_PLAYER_3,                        -1,
416     TYPE_BOOLEAN,                       CONF_VALUE_8_BIT(9),
417     &li.use_start_element[2],           FALSE
418   },
419   {
420     EL_PLAYER_3,                        -1,
421     TYPE_ELEMENT,                       CONF_VALUE_16_BIT(1),
422     &li.start_element[2],               EL_PLAYER_3
423   },
424   {
425     EL_PLAYER_3,                        -1,
426     TYPE_BOOLEAN,                       CONF_VALUE_8_BIT(10),
427     &li.use_artwork_element[2],         FALSE
428   },
429   {
430     EL_PLAYER_3,                        -1,
431     TYPE_ELEMENT,                       CONF_VALUE_16_BIT(2),
432     &li.artwork_element[2],             EL_PLAYER_3
433   },
434   {
435     EL_PLAYER_3,                        -1,
436     TYPE_BOOLEAN,                       CONF_VALUE_8_BIT(11),
437     &li.use_explosion_element[2],       FALSE
438   },
439   {
440     EL_PLAYER_3,                        -1,
441     TYPE_ELEMENT,                       CONF_VALUE_16_BIT(3),
442     &li.explosion_element[2],           EL_PLAYER_3
443   },
444   {
445     EL_PLAYER_3,                        -1,
446     TYPE_BOOLEAN,                       CONF_VALUE_8_BIT(13),
447     &li.use_initial_inventory[2],       FALSE
448   },
449   {
450     EL_PLAYER_3,                        -1,
451     TYPE_BOOLEAN,                       CONF_VALUE_8_BIT(14),
452     &li.initial_inventory_size[2],      1
453   },
454   {
455     EL_PLAYER_3,                        -1,
456     TYPE_ELEMENT_LIST,                  CONF_VALUE_BYTES(1),
457     &li.initial_inventory_content[2][0],EL_EMPTY, NULL,
458     &li.initial_inventory_size[2],      1, MAX_INITIAL_INVENTORY_SIZE
459   },
460
461   {
462     EL_PLAYER_4,                        -1,
463     TYPE_INTEGER,                       CONF_VALUE_8_BIT(7),
464     &li.initial_player_stepsize[3],     STEPSIZE_NORMAL
465   },
466   {
467     EL_PLAYER_4,                        -1,
468     TYPE_BOOLEAN,                       CONF_VALUE_8_BIT(8),
469     &li.initial_player_gravity[3],      FALSE
470   },
471   {
472     EL_PLAYER_4,                        -1,
473     TYPE_BOOLEAN,                       CONF_VALUE_8_BIT(9),
474     &li.use_start_element[3],           FALSE
475   },
476   {
477     EL_PLAYER_4,                        -1,
478     TYPE_ELEMENT,                       CONF_VALUE_16_BIT(1),
479     &li.start_element[3],               EL_PLAYER_4
480   },
481   {
482     EL_PLAYER_4,                        -1,
483     TYPE_BOOLEAN,                       CONF_VALUE_8_BIT(10),
484     &li.use_artwork_element[3],         FALSE
485   },
486   {
487     EL_PLAYER_4,                        -1,
488     TYPE_ELEMENT,                       CONF_VALUE_16_BIT(2),
489     &li.artwork_element[3],             EL_PLAYER_4
490   },
491   {
492     EL_PLAYER_4,                        -1,
493     TYPE_BOOLEAN,                       CONF_VALUE_8_BIT(11),
494     &li.use_explosion_element[3],       FALSE
495   },
496   {
497     EL_PLAYER_4,                        -1,
498     TYPE_ELEMENT,                       CONF_VALUE_16_BIT(3),
499     &li.explosion_element[3],           EL_PLAYER_4
500   },
501   {
502     EL_PLAYER_4,                        -1,
503     TYPE_BOOLEAN,                       CONF_VALUE_8_BIT(13),
504     &li.use_initial_inventory[3],       FALSE
505   },
506   {
507     EL_PLAYER_4,                        -1,
508     TYPE_BOOLEAN,                       CONF_VALUE_8_BIT(14),
509     &li.initial_inventory_size[3],      1
510   },
511   {
512     EL_PLAYER_4,                        -1,
513     TYPE_ELEMENT_LIST,                  CONF_VALUE_BYTES(1),
514     &li.initial_inventory_content[3][0],EL_EMPTY, NULL,
515     &li.initial_inventory_size[3],      1, MAX_INITIAL_INVENTORY_SIZE
516   },
517
518   {
519     EL_EMERALD,                         -1,
520     TYPE_INTEGER,                       CONF_VALUE_16_BIT(1),
521     &li.score[SC_EMERALD],              10
522   },
523
524   {
525     EL_DIAMOND,                         -1,
526     TYPE_INTEGER,                       CONF_VALUE_16_BIT(1),
527     &li.score[SC_DIAMOND],              10
528   },
529
530   {
531     EL_BUG,                             -1,
532     TYPE_INTEGER,                       CONF_VALUE_16_BIT(1),
533     &li.score[SC_BUG],                  10
534   },
535
536   {
537     EL_SPACESHIP,                       -1,
538     TYPE_INTEGER,                       CONF_VALUE_16_BIT(1),
539     &li.score[SC_SPACESHIP],            10
540   },
541
542   {
543     EL_PACMAN,                          -1,
544     TYPE_INTEGER,                       CONF_VALUE_16_BIT(1),
545     &li.score[SC_PACMAN],               10
546   },
547
548   {
549     EL_NUT,                             -1,
550     TYPE_INTEGER,                       CONF_VALUE_16_BIT(1),
551     &li.score[SC_NUT],                  10
552   },
553
554   {
555     EL_DYNAMITE,                        -1,
556     TYPE_INTEGER,                       CONF_VALUE_16_BIT(1),
557     &li.score[SC_DYNAMITE],             10
558   },
559
560   {
561     EL_KEY_1,                           -1,
562     TYPE_INTEGER,                       CONF_VALUE_16_BIT(1),
563     &li.score[SC_KEY],                  10
564   },
565
566   {
567     EL_PEARL,                           -1,
568     TYPE_INTEGER,                       CONF_VALUE_16_BIT(1),
569     &li.score[SC_PEARL],                10
570   },
571
572   {
573     EL_CRYSTAL,                         -1,
574     TYPE_INTEGER,                       CONF_VALUE_16_BIT(1),
575     &li.score[SC_CRYSTAL],              10
576   },
577
578   {
579     EL_BD_AMOEBA,                       -1,
580     TYPE_ELEMENT,                       CONF_VALUE_16_BIT(1),
581     &li.amoeba_content,                 EL_DIAMOND
582   },
583   {
584     EL_BD_AMOEBA,                       -1,
585     TYPE_INTEGER,                       CONF_VALUE_16_BIT(2),
586     &li.amoeba_speed,                   10
587   },
588   {
589     EL_BD_AMOEBA,                       -1,
590     TYPE_BOOLEAN,                       CONF_VALUE_8_BIT(1),
591     &li.grow_into_diggable,             TRUE
592   },
593
594   {
595     EL_YAMYAM,                          -1,
596     TYPE_CONTENT_LIST,                  CONF_VALUE_BYTES(1),
597     &li.yamyam_content,                 EL_ROCK, NULL,
598     &li.num_yamyam_contents,            4, MAX_ELEMENT_CONTENTS
599   },
600   {
601     EL_YAMYAM,                          -1,
602     TYPE_INTEGER,                       CONF_VALUE_16_BIT(1),
603     &li.score[SC_YAMYAM],               10
604   },
605
606   {
607     EL_ROBOT,                           -1,
608     TYPE_INTEGER,                       CONF_VALUE_16_BIT(1),
609     &li.score[SC_ROBOT],                10
610   },
611   {
612     EL_ROBOT,                           -1,
613     TYPE_INTEGER,                       CONF_VALUE_16_BIT(2),
614     &li.slurp_score,                    10
615   },
616
617   {
618     EL_ROBOT_WHEEL,                     -1,
619     TYPE_INTEGER,                       CONF_VALUE_16_BIT(1),
620     &li.time_wheel,                     10
621   },
622
623   {
624     EL_MAGIC_WALL,                      -1,
625     TYPE_INTEGER,                       CONF_VALUE_16_BIT(1),
626     &li.time_magic_wall,                10
627   },
628
629   {
630     EL_GAME_OF_LIFE,                    -1,
631     TYPE_INTEGER,                       CONF_VALUE_8_BIT(1),
632     &li.game_of_life[0],                2
633   },
634   {
635     EL_GAME_OF_LIFE,                    -1,
636     TYPE_INTEGER,                       CONF_VALUE_8_BIT(2),
637     &li.game_of_life[1],                3
638   },
639   {
640     EL_GAME_OF_LIFE,                    -1,
641     TYPE_INTEGER,                       CONF_VALUE_8_BIT(3),
642     &li.game_of_life[2],                3
643   },
644   {
645     EL_GAME_OF_LIFE,                    -1,
646     TYPE_INTEGER,                       CONF_VALUE_8_BIT(4),
647     &li.game_of_life[3],                3
648   },
649
650   {
651     EL_BIOMAZE,                         -1,
652     TYPE_INTEGER,                       CONF_VALUE_8_BIT(1),
653     &li.biomaze[0],                     2
654   },
655   {
656     EL_BIOMAZE,                         -1,
657     TYPE_INTEGER,                       CONF_VALUE_8_BIT(2),
658     &li.biomaze[1],                     3
659   },
660   {
661     EL_BIOMAZE,                         -1,
662     TYPE_INTEGER,                       CONF_VALUE_8_BIT(3),
663     &li.biomaze[2],                     3
664   },
665   {
666     EL_BIOMAZE,                         -1,
667     TYPE_INTEGER,                       CONF_VALUE_8_BIT(4),
668     &li.biomaze[3],                     3
669   },
670
671   {
672     EL_TIMEGATE_SWITCH,                 -1,
673     TYPE_INTEGER,                       CONF_VALUE_16_BIT(1),
674     &li.time_timegate,                  10
675   },
676
677   {
678     EL_LIGHT_SWITCH_ACTIVE,             -1,
679     TYPE_INTEGER,                       CONF_VALUE_16_BIT(1),
680     &li.time_light,                     10
681   },
682
683   {
684     EL_SHIELD_NORMAL,                   -1,
685     TYPE_INTEGER,                       CONF_VALUE_16_BIT(1),
686     &li.shield_normal_time,             10
687   },
688   {
689     EL_SHIELD_NORMAL,                   -1,
690     TYPE_INTEGER,                       CONF_VALUE_16_BIT(2),
691     &li.score[SC_SHIELD],               10
692   },
693
694   {
695     EL_SHIELD_DEADLY,                   -1,
696     TYPE_INTEGER,                       CONF_VALUE_16_BIT(1),
697     &li.shield_deadly_time,             10
698   },
699   {
700     EL_SHIELD_DEADLY,                   -1,
701     TYPE_INTEGER,                       CONF_VALUE_16_BIT(2),
702     &li.score[SC_SHIELD],               10
703   },
704
705   {
706     EL_EXTRA_TIME,                      -1,
707     TYPE_INTEGER,                       CONF_VALUE_16_BIT(1),
708     &li.extra_time,                     10
709   },
710   {
711     EL_EXTRA_TIME,                      -1,
712     TYPE_INTEGER,                       CONF_VALUE_16_BIT(2),
713     &li.extra_time_score,               10
714   },
715
716   {
717     EL_TIME_ORB_FULL,                   -1,
718     TYPE_INTEGER,                       CONF_VALUE_16_BIT(1),
719     &li.time_orb_time,                  10
720   },
721   {
722     EL_TIME_ORB_FULL,                   -1,
723     TYPE_BOOLEAN,                       CONF_VALUE_8_BIT(1),
724     &li.use_time_orb_bug,               FALSE
725   },
726
727   {
728     EL_SPRING,                          -1,
729     TYPE_BOOLEAN,                       CONF_VALUE_8_BIT(1),
730     &li.use_spring_bug,                 FALSE
731   },
732
733   {
734     EL_EMC_ANDROID,                     -1,
735     TYPE_INTEGER,                       CONF_VALUE_16_BIT(1),
736     &li.android_move_time,              10
737   },
738   {
739     EL_EMC_ANDROID,                     -1,
740     TYPE_INTEGER,                       CONF_VALUE_16_BIT(2),
741     &li.android_clone_time,             10
742   },
743   {
744     EL_EMC_ANDROID,                     -1,
745     TYPE_ELEMENT_LIST,                  CONF_VALUE_BYTES(1),
746     &li.android_clone_element[0],       EL_EMPTY, NULL,
747     &li.num_android_clone_elements,     1, MAX_ANDROID_ELEMENTS
748   },
749
750   {
751     EL_EMC_LENSES,                      -1,
752     TYPE_INTEGER,                       CONF_VALUE_16_BIT(1),
753     &li.lenses_score,                   10
754   },
755   {
756     EL_EMC_LENSES,                      -1,
757     TYPE_INTEGER,                       CONF_VALUE_16_BIT(2),
758     &li.lenses_time,                    10
759   },
760
761   {
762     EL_EMC_MAGNIFIER,                   -1,
763     TYPE_INTEGER,                       CONF_VALUE_16_BIT(1),
764     &li.magnify_score,                  10
765   },
766   {
767     EL_EMC_MAGNIFIER,                   -1,
768     TYPE_INTEGER,                       CONF_VALUE_16_BIT(2),
769     &li.magnify_time,                   10
770   },
771
772   {
773     EL_EMC_MAGIC_BALL,                  -1,
774     TYPE_INTEGER,                       CONF_VALUE_16_BIT(1),
775     &li.ball_time,                      10
776   },
777   {
778     EL_EMC_MAGIC_BALL,                  -1,
779     TYPE_BOOLEAN,                       CONF_VALUE_8_BIT(1),
780     &li.ball_random,                    FALSE
781   },
782   {
783     EL_EMC_MAGIC_BALL,                  -1,
784     TYPE_BOOLEAN,                       CONF_VALUE_8_BIT(2),
785     &li.ball_state_initial,             FALSE
786   },
787   {
788     EL_EMC_MAGIC_BALL,                  -1,
789     TYPE_CONTENT_LIST,                  CONF_VALUE_BYTES(1),
790     &li.ball_content,                   EL_EMPTY, NULL,
791     &li.num_ball_contents,              4, MAX_ELEMENT_CONTENTS
792   },
793
794   /* ---------- unused values ----------------------------------------------- */
795
796   {
797     EL_UNKNOWN,                         SAVE_CONF_NEVER,
798     TYPE_INTEGER,                       CONF_VALUE_16_BIT(1),
799     &li.score[SC_UNKNOWN_14],           10
800   },
801   {
802     EL_UNKNOWN,                         SAVE_CONF_NEVER,
803     TYPE_INTEGER,                       CONF_VALUE_16_BIT(2),
804     &li.score[SC_UNKNOWN_15],           10
805   },
806
807   {
808     -1,                                 -1,
809     -1,                                 -1,
810     NULL,                               -1
811   }
812 };
813
814 static struct LevelFileConfigInfo chunk_config_NOTE[] =
815 {
816   {
817     -1,                                 -1,
818     TYPE_INTEGER,                       CONF_VALUE_8_BIT(1),
819     &xx_envelope.xsize,                 MAX_ENVELOPE_XSIZE,
820   },
821   {
822     -1,                                 -1,
823     TYPE_INTEGER,                       CONF_VALUE_8_BIT(2),
824     &xx_envelope.ysize,                 MAX_ENVELOPE_YSIZE,
825   },
826
827   {
828     -1,                                 -1,
829     TYPE_BOOLEAN,                       CONF_VALUE_8_BIT(3),
830     &xx_envelope.autowrap,              FALSE
831   },
832   {
833     -1,                                 -1,
834     TYPE_BOOLEAN,                       CONF_VALUE_8_BIT(4),
835     &xx_envelope.centered,              FALSE
836   },
837
838   {
839     -1,                                 -1,
840     TYPE_STRING,                        CONF_VALUE_BYTES(1),
841     &xx_envelope.text,                  -1, NULL,
842     &xx_string_length_unused,           -1, MAX_ENVELOPE_TEXT_LEN,
843     &xx_default_string_empty[0]
844   },
845
846   {
847     -1,                                 -1,
848     -1,                                 -1,
849     NULL,                               -1
850   }
851 };
852
853 static struct LevelFileConfigInfo chunk_config_CUSX_base[] =
854 {
855   {
856     -1,                                 -1,
857     TYPE_STRING,                        CONF_VALUE_BYTES(1),
858     &xx_ei.description[0],              -1,
859     &yy_ei.description[0],
860     &xx_string_length_unused,           -1, MAX_ELEMENT_NAME_LEN,
861     &xx_default_description[0]
862   },
863
864   {
865     -1,                                 -1,
866     TYPE_BITFIELD,                      CONF_VALUE_32_BIT(1),
867     &xx_ei.properties[EP_BITFIELD_BASE_NR], EP_BITMASK_BASE_DEFAULT,
868     &yy_ei.properties[EP_BITFIELD_BASE_NR]
869   },
870 #if 0
871   /* (reserved) */
872   {
873     -1,                                 -1,
874     TYPE_BITFIELD,                      CONF_VALUE_32_BIT(2),
875     &xx_ei.properties[EP_BITFIELD_BASE_NR + 1], EP_BITMASK_DEFAULT,
876     &yy_ei.properties[EP_BITFIELD_BASE_NR + 1]
877   },
878 #endif
879
880   {
881     -1,                                 -1,
882     TYPE_BOOLEAN,                       CONF_VALUE_8_BIT(1),
883     &xx_ei.use_gfx_element,             FALSE,
884     &yy_ei.use_gfx_element
885   },
886   {
887     -1,                                 -1,
888     TYPE_ELEMENT,                       CONF_VALUE_16_BIT(1),
889     &xx_ei.gfx_element_initial,         EL_EMPTY_SPACE,
890     &yy_ei.gfx_element_initial
891   },
892
893   {
894     -1,                                 -1,
895     TYPE_BITFIELD,                      CONF_VALUE_8_BIT(2),
896     &xx_ei.access_direction,            MV_ALL_DIRECTIONS,
897     &yy_ei.access_direction
898   },
899
900   {
901     -1,                                 -1,
902     TYPE_INTEGER,                       CONF_VALUE_16_BIT(2),
903     &xx_ei.collect_score_initial,       10,
904     &yy_ei.collect_score_initial
905   },
906   {
907     -1,                                 -1,
908     TYPE_INTEGER,                       CONF_VALUE_16_BIT(3),
909     &xx_ei.collect_count_initial,       1,
910     &yy_ei.collect_count_initial
911   },
912
913   {
914     -1,                                 -1,
915     TYPE_INTEGER,                       CONF_VALUE_16_BIT(4),
916     &xx_ei.ce_value_fixed_initial,      0,
917     &yy_ei.ce_value_fixed_initial
918   },
919   {
920     -1,                                 -1,
921     TYPE_INTEGER,                       CONF_VALUE_16_BIT(5),
922     &xx_ei.ce_value_random_initial,     0,
923     &yy_ei.ce_value_random_initial
924   },
925   {
926     -1,                                 -1,
927     TYPE_BOOLEAN,                       CONF_VALUE_8_BIT(3),
928     &xx_ei.use_last_ce_value,           FALSE,
929     &yy_ei.use_last_ce_value
930   },
931
932   {
933     -1,                                 -1,
934     TYPE_INTEGER,                       CONF_VALUE_16_BIT(6),
935     &xx_ei.push_delay_fixed,            8,
936     &yy_ei.push_delay_fixed
937   },
938   {
939     -1,                                 -1,
940     TYPE_INTEGER,                       CONF_VALUE_16_BIT(7),
941     &xx_ei.push_delay_random,           8,
942     &yy_ei.push_delay_random
943   },
944   {
945     -1,                                 -1,
946     TYPE_INTEGER,                       CONF_VALUE_16_BIT(8),
947     &xx_ei.drop_delay_fixed,            0,
948     &yy_ei.drop_delay_fixed
949   },
950   {
951     -1,                                 -1,
952     TYPE_INTEGER,                       CONF_VALUE_16_BIT(9),
953     &xx_ei.drop_delay_random,           0,
954     &yy_ei.drop_delay_random
955   },
956   {
957     -1,                                 -1,
958     TYPE_INTEGER,                       CONF_VALUE_16_BIT(10),
959     &xx_ei.move_delay_fixed,            0,
960     &yy_ei.move_delay_fixed
961   },
962   {
963     -1,                                 -1,
964     TYPE_INTEGER,                       CONF_VALUE_16_BIT(11),
965     &xx_ei.move_delay_random,           0,
966     &yy_ei.move_delay_random
967   },
968
969   {
970     -1,                                 -1,
971     TYPE_BITFIELD,                      CONF_VALUE_32_BIT(3),
972     &xx_ei.move_pattern,                MV_ALL_DIRECTIONS,
973     &yy_ei.move_pattern
974   },
975   {
976     -1,                                 -1,
977     TYPE_BITFIELD,                      CONF_VALUE_8_BIT(4),
978     &xx_ei.move_direction_initial,      MV_START_AUTOMATIC,
979     &yy_ei.move_direction_initial
980   },
981   {
982     -1,                                 -1,
983     TYPE_INTEGER,                       CONF_VALUE_8_BIT(5),
984     &xx_ei.move_stepsize,               TILEX / 8,
985     &yy_ei.move_stepsize
986   },
987
988   {
989     -1,                                 -1,
990     TYPE_ELEMENT,                       CONF_VALUE_16_BIT(12),
991     &xx_ei.move_enter_element,          EL_EMPTY_SPACE,
992     &yy_ei.move_enter_element
993   },
994   {
995     -1,                                 -1,
996     TYPE_ELEMENT,                       CONF_VALUE_16_BIT(13),
997     &xx_ei.move_leave_element,          EL_EMPTY_SPACE,
998     &yy_ei.move_leave_element
999   },
1000   {
1001     -1,                                 -1,
1002     TYPE_INTEGER,                       CONF_VALUE_8_BIT(6),
1003     &xx_ei.move_leave_type,             LEAVE_TYPE_UNLIMITED,
1004     &yy_ei.move_leave_type
1005   },
1006
1007   {
1008     -1,                                 -1,
1009     TYPE_INTEGER,                       CONF_VALUE_8_BIT(7),
1010     &xx_ei.slippery_type,               SLIPPERY_ANY_RANDOM,
1011     &yy_ei.slippery_type
1012   },
1013
1014   {
1015     -1,                                 -1,
1016     TYPE_INTEGER,                       CONF_VALUE_8_BIT(8),
1017     &xx_ei.explosion_type,              EXPLODES_3X3,
1018     &yy_ei.explosion_type
1019   },
1020   {
1021     -1,                                 -1,
1022     TYPE_INTEGER,                       CONF_VALUE_16_BIT(14),
1023     &xx_ei.explosion_delay,             16,
1024     &yy_ei.explosion_delay
1025   },
1026   {
1027     -1,                                 -1,
1028     TYPE_INTEGER,                       CONF_VALUE_16_BIT(15),
1029     &xx_ei.ignition_delay,              8,
1030     &yy_ei.ignition_delay
1031   },
1032
1033   {
1034     -1,                                 -1,
1035     TYPE_CONTENT_LIST,                  CONF_VALUE_BYTES(2),
1036     &xx_ei.content,                     EL_EMPTY_SPACE,
1037     &yy_ei.content,
1038     &xx_num_contents,                   1, 1
1039   },
1040
1041   /* ---------- "num_change_pages" must be the last entry ------------------- */
1042
1043   {
1044     -1,                                 SAVE_CONF_ALWAYS,
1045     TYPE_INTEGER,                       CONF_VALUE_8_BIT(9),
1046     &xx_ei.num_change_pages,            1,
1047     &yy_ei.num_change_pages
1048   },
1049
1050   {
1051     -1,                                 -1,
1052     -1,                                 -1,
1053     NULL,                               -1,
1054     NULL
1055   }
1056 };
1057
1058 static struct LevelFileConfigInfo chunk_config_CUSX_change[] =
1059 {
1060   /* ---------- "current_change_page" must be the first entry --------------- */
1061
1062   {
1063     -1,                                 SAVE_CONF_ALWAYS,
1064     TYPE_INTEGER,                       CONF_VALUE_8_BIT(1),
1065     &xx_current_change_page,            -1
1066   },
1067
1068   /* ---------- (the remaining entries can be in any order) ----------------- */
1069
1070   {
1071     -1,                                 -1,
1072     TYPE_BOOLEAN,                       CONF_VALUE_8_BIT(2),
1073     &xx_change.can_change,              FALSE
1074   },
1075
1076   {
1077     -1,                                 -1,
1078     TYPE_BITFIELD,                      CONF_VALUE_32_BIT(1),
1079     &xx_event_bits[0],                  0
1080   },
1081   {
1082     -1,                                 -1,
1083     TYPE_BITFIELD,                      CONF_VALUE_32_BIT(2),
1084     &xx_event_bits[1],                  0
1085   },
1086
1087   {
1088     -1,                                 -1,
1089     TYPE_BITFIELD,                      CONF_VALUE_8_BIT(3),
1090     &xx_change.trigger_player,          CH_PLAYER_ANY
1091   },
1092   {
1093     -1,                                 -1,
1094     TYPE_BITFIELD,                      CONF_VALUE_8_BIT(4),
1095     &xx_change.trigger_side,            CH_SIDE_ANY
1096   },
1097   {
1098     -1,                                 -1,
1099     TYPE_BITFIELD,                      CONF_VALUE_32_BIT(3),
1100     &xx_change.trigger_page,            CH_PAGE_ANY
1101   },
1102
1103   {
1104     -1,                                 -1,
1105     TYPE_ELEMENT,                       CONF_VALUE_16_BIT(1),
1106     &xx_change.target_element,          EL_EMPTY_SPACE
1107   },
1108
1109   {
1110     -1,                                 -1,
1111     TYPE_INTEGER,                       CONF_VALUE_16_BIT(2),
1112     &xx_change.delay_fixed,             0
1113   },
1114   {
1115     -1,                                 -1,
1116     TYPE_INTEGER,                       CONF_VALUE_16_BIT(3),
1117     &xx_change.delay_random,            0
1118   },
1119   {
1120     -1,                                 -1,
1121     TYPE_INTEGER,                       CONF_VALUE_16_BIT(4),
1122     &xx_change.delay_frames,            FRAMES_PER_SECOND
1123   },
1124
1125   {
1126     -1,                                 -1,
1127     TYPE_ELEMENT,                       CONF_VALUE_16_BIT(5),
1128     &xx_change.initial_trigger_element, EL_EMPTY_SPACE
1129   },
1130
1131   {
1132     -1,                                 -1,
1133     TYPE_BOOLEAN,                       CONF_VALUE_8_BIT(6),
1134     &xx_change.explode,                 FALSE
1135   },
1136   {
1137     -1,                                 -1,
1138     TYPE_BOOLEAN,                       CONF_VALUE_8_BIT(7),
1139     &xx_change.use_target_content,      FALSE
1140   },
1141   {
1142     -1,                                 -1,
1143     TYPE_BOOLEAN,                       CONF_VALUE_8_BIT(8),
1144     &xx_change.only_if_complete,        FALSE
1145   },
1146   {
1147     -1,                                 -1,
1148     TYPE_BOOLEAN,                       CONF_VALUE_8_BIT(9),
1149     &xx_change.use_random_replace,      FALSE
1150   },
1151   {
1152     -1,                                 -1,
1153     TYPE_INTEGER,                       CONF_VALUE_8_BIT(10),
1154     &xx_change.random_percentage,       100
1155   },
1156   {
1157     -1,                                 -1,
1158     TYPE_INTEGER,                       CONF_VALUE_8_BIT(11),
1159     &xx_change.replace_when,            CP_WHEN_EMPTY
1160   },
1161
1162   {
1163     -1,                                 -1,
1164     TYPE_BOOLEAN,                       CONF_VALUE_8_BIT(12),
1165     &xx_change.has_action,              FALSE
1166   },
1167   {
1168     -1,                                 -1,
1169     TYPE_INTEGER,                       CONF_VALUE_8_BIT(13),
1170     &xx_change.action_type,             CA_NO_ACTION
1171   },
1172   {
1173     -1,                                 -1,
1174     TYPE_INTEGER,                       CONF_VALUE_8_BIT(14),
1175     &xx_change.action_mode,             CA_MODE_UNDEFINED
1176   },
1177   {
1178     -1,                                 -1,
1179     TYPE_INTEGER,                       CONF_VALUE_16_BIT(6),
1180     &xx_change.action_arg,              CA_ARG_UNDEFINED
1181   },
1182
1183   {
1184     -1,                                 -1,
1185     TYPE_ELEMENT,                       CONF_VALUE_16_BIT(7),
1186     &xx_change.action_element,          EL_EMPTY_SPACE
1187   },
1188
1189   {
1190     -1,                                 -1,
1191     TYPE_CONTENT_LIST,                  CONF_VALUE_BYTES(1),
1192     &xx_change.target_content,          EL_EMPTY_SPACE, NULL,
1193     &xx_num_contents,                   1, 1
1194   },
1195
1196   {
1197     -1,                                 -1,
1198     -1,                                 -1,
1199     NULL,                               -1
1200   }
1201 };
1202
1203 static struct LevelFileConfigInfo chunk_config_GRPX[] =
1204 {
1205   {
1206     -1,                                 -1,
1207     TYPE_STRING,                        CONF_VALUE_BYTES(1),
1208     &xx_ei.description[0],              -1, NULL,
1209     &xx_string_length_unused,           -1, MAX_ELEMENT_NAME_LEN,
1210     &xx_default_description[0]
1211   },
1212
1213   {
1214     -1,                                 -1,
1215     TYPE_BOOLEAN,                       CONF_VALUE_8_BIT(1),
1216     &xx_ei.use_gfx_element,             FALSE
1217   },
1218   {
1219     -1,                                 -1,
1220     TYPE_ELEMENT,                       CONF_VALUE_16_BIT(1),
1221     &xx_ei.gfx_element_initial,         EL_EMPTY_SPACE
1222   },
1223
1224   {
1225     -1,                                 -1,
1226     TYPE_INTEGER,                       CONF_VALUE_8_BIT(2),
1227     &xx_group.choice_mode,              ANIM_RANDOM
1228   },
1229
1230   {
1231     -1,                                 -1,
1232     TYPE_ELEMENT_LIST,                  CONF_VALUE_BYTES(2),
1233     &xx_group.element[0],               EL_EMPTY_SPACE, NULL,
1234     &xx_group.num_elements,             1, MAX_ELEMENTS_IN_GROUP
1235   },
1236
1237   {
1238     -1,                                 -1,
1239     -1,                                 -1,
1240     NULL,                               -1
1241   }
1242 };
1243
1244 static struct LevelFileConfigInfo chunk_config_CONF[] =         /* (OBSOLETE) */
1245 {
1246   {
1247     EL_PLAYER_1,                        -1,
1248     TYPE_BOOLEAN,                       CONF_VALUE_8_BIT(9),
1249     &li.block_snap_field,               TRUE
1250   },
1251   {
1252     EL_PLAYER_1,                        -1,
1253     TYPE_BOOLEAN,                       CONF_VALUE_8_BIT(13),
1254     &li.continuous_snapping,            TRUE
1255   },
1256   {
1257     EL_PLAYER_1,                        -1,
1258     TYPE_INTEGER,                       CONF_VALUE_8_BIT(1),
1259     &li.initial_player_stepsize[0],     STEPSIZE_NORMAL
1260   },
1261   {
1262     EL_PLAYER_1,                        -1,
1263     TYPE_BOOLEAN,                       CONF_VALUE_8_BIT(10),
1264     &li.use_start_element[0],           FALSE
1265   },
1266   {
1267     EL_PLAYER_1,                        -1,
1268     TYPE_ELEMENT,                       CONF_VALUE_16_BIT(1),
1269     &li.start_element[0],               EL_PLAYER_1
1270   },
1271   {
1272     EL_PLAYER_1,                        -1,
1273     TYPE_BOOLEAN,                       CONF_VALUE_8_BIT(11),
1274     &li.use_artwork_element[0],         FALSE
1275   },
1276   {
1277     EL_PLAYER_1,                        -1,
1278     TYPE_ELEMENT,                       CONF_VALUE_16_BIT(2),
1279     &li.artwork_element[0],             EL_PLAYER_1
1280   },
1281   {
1282     EL_PLAYER_1,                        -1,
1283     TYPE_BOOLEAN,                       CONF_VALUE_8_BIT(12),
1284     &li.use_explosion_element[0],       FALSE
1285   },
1286   {
1287     EL_PLAYER_1,                        -1,
1288     TYPE_ELEMENT,                       CONF_VALUE_16_BIT(3),
1289     &li.explosion_element[0],           EL_PLAYER_1
1290   },
1291
1292   {
1293     -1,                                 -1,
1294     -1,                                 -1,
1295     NULL,                               -1
1296   }
1297 };
1298
1299 static struct
1300 {
1301   int filetype;
1302   char *id;
1303 }
1304 filetype_id_list[] =
1305 {
1306   { LEVEL_FILE_TYPE_RND,        "RND"   },
1307   { LEVEL_FILE_TYPE_BD,         "BD"    },
1308   { LEVEL_FILE_TYPE_EM,         "EM"    },
1309   { LEVEL_FILE_TYPE_SP,         "SP"    },
1310   { LEVEL_FILE_TYPE_DX,         "DX"    },
1311   { LEVEL_FILE_TYPE_SB,         "SB"    },
1312   { LEVEL_FILE_TYPE_DC,         "DC"    },
1313   { -1,                         NULL    },
1314 };
1315
1316
1317 /* ========================================================================= */
1318 /* level file functions                                                      */
1319 /* ========================================================================= */
1320
1321 static boolean check_special_flags(char *flag)
1322 {
1323 #if 0
1324   printf("::: '%s', '%s', '%s'\n",
1325          flag,
1326          options.special_flags,
1327          leveldir_current->special_flags);
1328 #endif
1329
1330   if (strEqual(options.special_flags, flag) ||
1331       strEqual(leveldir_current->special_flags, flag))
1332     return TRUE;
1333
1334   return FALSE;
1335 }
1336
1337 static struct DateInfo getCurrentDate()
1338 {
1339   time_t epoch_seconds = time(NULL);
1340   struct tm *now = localtime(&epoch_seconds);
1341   struct DateInfo date;
1342
1343   date.year  = now->tm_year + 1900;
1344   date.month = now->tm_mon  + 1;
1345   date.day   = now->tm_mday;
1346
1347   date.src   = DATE_SRC_CLOCK;
1348
1349   return date;
1350 }
1351
1352 static void resetEventFlags(struct ElementChangeInfo *change)
1353 {
1354   int i;
1355
1356   for (i = 0; i < NUM_CHANGE_EVENTS; i++)
1357     change->has_event[i] = FALSE;
1358 }
1359
1360 static void resetEventBits()
1361 {
1362   int i;
1363
1364   for (i = 0; i < NUM_CE_BITFIELDS; i++)
1365     xx_event_bits[i] = 0;
1366 }
1367
1368 static void setEventFlagsFromEventBits(struct ElementChangeInfo *change)
1369 {
1370   int i;
1371
1372   /* important: only change event flag if corresponding event bit is set
1373      (this is because all xx_event_bits[] values are loaded separately,
1374      and all xx_event_bits[] values are set back to zero before loading
1375      another value xx_event_bits[x] (each value representing 32 flags)) */
1376
1377   for (i = 0; i < NUM_CHANGE_EVENTS; i++)
1378     if (xx_event_bits[CH_EVENT_BITFIELD_NR(i)] & CH_EVENT_BIT(i))
1379       change->has_event[i] = TRUE;
1380 }
1381
1382 static void setEventBitsFromEventFlags(struct ElementChangeInfo *change)
1383 {
1384   int i;
1385
1386   /* in contrast to the above function setEventFlagsFromEventBits(), it
1387      would also be possible to set all bits in xx_event_bits[] to 0 or 1
1388      depending on the corresponding change->has_event[i] values here, as
1389      all xx_event_bits[] values are reset in resetEventBits() before */
1390
1391   for (i = 0; i < NUM_CHANGE_EVENTS; i++)
1392     if (change->has_event[i])
1393       xx_event_bits[CH_EVENT_BITFIELD_NR(i)] |= CH_EVENT_BIT(i);
1394 }
1395
1396 static char *getDefaultElementDescription(struct ElementInfo *ei)
1397 {
1398   static char description[MAX_ELEMENT_NAME_LEN + 1];
1399   char *default_description = (ei->custom_description != NULL ?
1400                                ei->custom_description :
1401                                ei->editor_description);
1402   int i;
1403
1404   /* always start with reliable default values */
1405   for (i = 0; i < MAX_ELEMENT_NAME_LEN + 1; i++)
1406     description[i] = '\0';
1407
1408   /* truncate element description to MAX_ELEMENT_NAME_LEN bytes */
1409   strncpy(description, default_description, MAX_ELEMENT_NAME_LEN);
1410
1411   return &description[0];
1412 }
1413
1414 static void setElementDescriptionToDefault(struct ElementInfo *ei)
1415 {
1416   char *default_description = getDefaultElementDescription(ei);
1417   int i;
1418
1419   for (i = 0; i < MAX_ELEMENT_NAME_LEN + 1; i++)
1420     ei->description[i] = default_description[i];
1421 }
1422
1423 static void setConfigToDefaultsFromConfigList(struct LevelFileConfigInfo *conf)
1424 {
1425   int i;
1426
1427   for (i = 0; conf[i].data_type != -1; i++)
1428   {
1429     int default_value = conf[i].default_value;
1430     int data_type = conf[i].data_type;
1431     int conf_type = conf[i].conf_type;
1432     int byte_mask = conf_type & CONF_MASK_BYTES;
1433
1434     if (byte_mask == CONF_MASK_MULTI_BYTES)
1435     {
1436       int default_num_entities = conf[i].default_num_entities;
1437       int max_num_entities = conf[i].max_num_entities;
1438
1439       *(int *)(conf[i].num_entities) = default_num_entities;
1440
1441       if (data_type == TYPE_STRING)
1442       {
1443         char *default_string = conf[i].default_string;
1444         char *string = (char *)(conf[i].value);
1445
1446         strncpy(string, default_string, max_num_entities);
1447       }
1448       else if (data_type == TYPE_ELEMENT_LIST)
1449       {
1450         int *element_array = (int *)(conf[i].value);
1451         int j;
1452
1453         for (j = 0; j < max_num_entities; j++)
1454           element_array[j] = default_value;
1455       }
1456       else if (data_type == TYPE_CONTENT_LIST)
1457       {
1458         struct Content *content = (struct Content *)(conf[i].value);
1459         int c, x, y;
1460
1461         for (c = 0; c < max_num_entities; c++)
1462           for (y = 0; y < 3; y++)
1463             for (x = 0; x < 3; x++)
1464               content[c].e[x][y] = default_value;
1465       }
1466     }
1467     else        /* constant size configuration data (1, 2 or 4 bytes) */
1468     {
1469       if (data_type == TYPE_BOOLEAN)
1470         *(boolean *)(conf[i].value) = default_value;
1471       else
1472         *(int *)    (conf[i].value) = default_value;
1473     }
1474   }
1475 }
1476
1477 static void copyConfigFromConfigList(struct LevelFileConfigInfo *conf)
1478 {
1479   int i;
1480
1481   for (i = 0; conf[i].data_type != -1; i++)
1482   {
1483     int data_type = conf[i].data_type;
1484     int conf_type = conf[i].conf_type;
1485     int byte_mask = conf_type & CONF_MASK_BYTES;
1486
1487     if (byte_mask == CONF_MASK_MULTI_BYTES)
1488     {
1489       int max_num_entities = conf[i].max_num_entities;
1490
1491       if (data_type == TYPE_STRING)
1492       {
1493         char *string      = (char *)(conf[i].value);
1494         char *string_copy = (char *)(conf[i].value_copy);
1495
1496         strncpy(string_copy, string, max_num_entities);
1497       }
1498       else if (data_type == TYPE_ELEMENT_LIST)
1499       {
1500         int *element_array      = (int *)(conf[i].value);
1501         int *element_array_copy = (int *)(conf[i].value_copy);
1502         int j;
1503
1504         for (j = 0; j < max_num_entities; j++)
1505           element_array_copy[j] = element_array[j];
1506       }
1507       else if (data_type == TYPE_CONTENT_LIST)
1508       {
1509         struct Content *content      = (struct Content *)(conf[i].value);
1510         struct Content *content_copy = (struct Content *)(conf[i].value_copy);
1511         int c, x, y;
1512
1513         for (c = 0; c < max_num_entities; c++)
1514           for (y = 0; y < 3; y++)
1515             for (x = 0; x < 3; x++)
1516               content_copy[c].e[x][y] = content[c].e[x][y];
1517       }
1518     }
1519     else        /* constant size configuration data (1, 2 or 4 bytes) */
1520     {
1521       if (data_type == TYPE_BOOLEAN)
1522         *(boolean *)(conf[i].value_copy) = *(boolean *)(conf[i].value);
1523       else
1524         *(int *)    (conf[i].value_copy) = *(int *)    (conf[i].value);
1525     }
1526   }
1527 }
1528
1529 void copyElementInfo(struct ElementInfo *ei_from, struct ElementInfo *ei_to)
1530 {
1531   int i;
1532
1533   xx_ei = *ei_from;     /* copy element data into temporary buffer */
1534   yy_ei = *ei_to;       /* copy element data into temporary buffer */
1535
1536   copyConfigFromConfigList(chunk_config_CUSX_base);
1537
1538   *ei_from = xx_ei;
1539   *ei_to   = yy_ei;
1540
1541   /* ---------- reinitialize and copy change pages ---------- */
1542
1543   ei_to->num_change_pages = ei_from->num_change_pages;
1544   ei_to->current_change_page = ei_from->current_change_page;
1545
1546   setElementChangePages(ei_to, ei_to->num_change_pages);
1547
1548   for (i = 0; i < ei_to->num_change_pages; i++)
1549     ei_to->change_page[i] = ei_from->change_page[i];
1550
1551   /* ---------- copy group element info ---------- */
1552   if (ei_from->group != NULL && ei_to->group != NULL)   /* group or internal */
1553     *ei_to->group = *ei_from->group;
1554
1555   /* mark this custom element as modified */
1556   ei_to->modified_settings = TRUE;
1557 }
1558
1559 void setElementChangePages(struct ElementInfo *ei, int change_pages)
1560 {
1561   int change_page_size = sizeof(struct ElementChangeInfo);
1562
1563   ei->num_change_pages = MAX(1, change_pages);
1564
1565   ei->change_page =
1566     checked_realloc(ei->change_page, ei->num_change_pages * change_page_size);
1567
1568   if (ei->current_change_page >= ei->num_change_pages)
1569     ei->current_change_page = ei->num_change_pages - 1;
1570
1571   ei->change = &ei->change_page[ei->current_change_page];
1572 }
1573
1574 void setElementChangeInfoToDefaults(struct ElementChangeInfo *change)
1575 {
1576   xx_change = *change;          /* copy change data into temporary buffer */
1577
1578 #if 0
1579   /* (not needed; set by setConfigToDefaultsFromConfigList()) */
1580   xx_num_contents = 1;
1581 #endif
1582
1583   setConfigToDefaultsFromConfigList(chunk_config_CUSX_change);
1584
1585   *change = xx_change;
1586
1587   resetEventFlags(change);
1588
1589   change->direct_action = 0;
1590   change->other_action = 0;
1591
1592   change->pre_change_function = NULL;
1593   change->change_function = NULL;
1594   change->post_change_function = NULL;
1595 }
1596
1597 #if 1
1598
1599 static void setLevelInfoToDefaults_Level(struct LevelInfo *level)
1600 {
1601   int i, x, y;
1602
1603   li = *level;          /* copy level data into temporary buffer */
1604   setConfigToDefaultsFromConfigList(chunk_config_INFO);
1605   *level = li;          /* copy temporary buffer back to level data */
1606
1607   setLevelInfoToDefaults_EM();
1608   setLevelInfoToDefaults_SP();
1609
1610   level->native_em_level = &native_em_level;
1611   level->native_sp_level = &native_sp_level;
1612
1613   level->file_version = FILE_VERSION_ACTUAL;
1614   level->game_version = GAME_VERSION_ACTUAL;
1615
1616   level->creation_date = getCurrentDate();
1617
1618   level->encoding_16bit_field  = TRUE;
1619   level->encoding_16bit_yamyam = TRUE;
1620   level->encoding_16bit_amoeba = TRUE;
1621
1622   for (x = 0; x < MAX_LEV_FIELDX; x++)
1623     for (y = 0; y < MAX_LEV_FIELDY; y++)
1624       level->field[x][y] = EL_SAND;
1625
1626   for (i = 0; i < MAX_LEVEL_NAME_LEN; i++)
1627     level->name[i] = '\0';
1628   for (i = 0; i < MAX_LEVEL_AUTHOR_LEN; i++)
1629     level->author[i] = '\0';
1630
1631   strcpy(level->name, NAMELESS_LEVEL_NAME);
1632   strcpy(level->author, ANONYMOUS_NAME);
1633
1634   level->field[0][0] = EL_PLAYER_1;
1635   level->field[STD_LEV_FIELDX - 1][STD_LEV_FIELDY - 1] = EL_EXIT_CLOSED;
1636
1637   BorderElement = EL_STEELWALL;
1638
1639   /* set all bug compatibility flags to "false" => do not emulate this bug */
1640   level->use_action_after_change_bug = FALSE;
1641
1642   if (leveldir_current)
1643   {
1644     /* try to determine better author name than 'anonymous' */
1645     if (!strEqual(leveldir_current->author, ANONYMOUS_NAME))
1646     {
1647       strncpy(level->author, leveldir_current->author, MAX_LEVEL_AUTHOR_LEN);
1648       level->author[MAX_LEVEL_AUTHOR_LEN] = '\0';
1649     }
1650     else
1651     {
1652       switch (LEVELCLASS(leveldir_current))
1653       {
1654         case LEVELCLASS_TUTORIAL:
1655           strcpy(level->author, PROGRAM_AUTHOR_STRING);
1656           break;
1657
1658         case LEVELCLASS_CONTRIB:
1659           strncpy(level->author, leveldir_current->name, MAX_LEVEL_AUTHOR_LEN);
1660           level->author[MAX_LEVEL_AUTHOR_LEN] = '\0';
1661           break;
1662
1663         case LEVELCLASS_PRIVATE:
1664           strncpy(level->author, getRealName(), MAX_LEVEL_AUTHOR_LEN);
1665           level->author[MAX_LEVEL_AUTHOR_LEN] = '\0';
1666           break;
1667
1668         default:
1669           /* keep default value */
1670           break;
1671       }
1672     }
1673   }
1674 }
1675
1676 static void setLevelInfoToDefaults_Elements(struct LevelInfo *level)
1677 {
1678   static boolean clipboard_elements_initialized = FALSE;
1679   int i;
1680
1681   InitElementPropertiesStatic();
1682
1683   li = *level;          /* copy level data into temporary buffer */
1684   setConfigToDefaultsFromConfigList(chunk_config_ELEM);
1685   *level = li;          /* copy temporary buffer back to level data */
1686
1687   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
1688   {
1689     int element = i;
1690     struct ElementInfo *ei = &element_info[element];
1691
1692     /* never initialize clipboard elements after the very first time */
1693     /* (to be able to use clipboard elements between several levels) */
1694     if (IS_CLIPBOARD_ELEMENT(element) && clipboard_elements_initialized)
1695       continue;
1696
1697     if (IS_ENVELOPE(element))
1698     {
1699       int envelope_nr = element - EL_ENVELOPE_1;
1700
1701       setConfigToDefaultsFromConfigList(chunk_config_NOTE);
1702
1703       level->envelope[envelope_nr] = xx_envelope;
1704     }
1705
1706     if (IS_CUSTOM_ELEMENT(element) ||
1707         IS_GROUP_ELEMENT(element) ||
1708         IS_INTERNAL_ELEMENT(element))
1709     {
1710       xx_ei = *ei;      /* copy element data into temporary buffer */
1711
1712       setConfigToDefaultsFromConfigList(chunk_config_CUSX_base);
1713
1714       *ei = xx_ei;
1715     }
1716
1717     setElementChangePages(ei, 1);
1718     setElementChangeInfoToDefaults(ei->change);
1719
1720     if (IS_CUSTOM_ELEMENT(element) ||
1721         IS_GROUP_ELEMENT(element) ||
1722         IS_INTERNAL_ELEMENT(element))
1723     {
1724       setElementDescriptionToDefault(ei);
1725
1726       ei->modified_settings = FALSE;
1727     }
1728
1729     if (IS_CUSTOM_ELEMENT(element) ||
1730         IS_INTERNAL_ELEMENT(element))
1731     {
1732       /* internal values used in level editor */
1733
1734       ei->access_type = 0;
1735       ei->access_layer = 0;
1736       ei->access_protected = 0;
1737       ei->walk_to_action = 0;
1738       ei->smash_targets = 0;
1739       ei->deadliness = 0;
1740
1741       ei->can_explode_by_fire = FALSE;
1742       ei->can_explode_smashed = FALSE;
1743       ei->can_explode_impact = FALSE;
1744
1745       ei->current_change_page = 0;
1746     }
1747
1748     if (IS_GROUP_ELEMENT(element) ||
1749         IS_INTERNAL_ELEMENT(element))
1750     {
1751       struct ElementGroupInfo *group;
1752
1753       /* initialize memory for list of elements in group */
1754       if (ei->group == NULL)
1755         ei->group = checked_malloc(sizeof(struct ElementGroupInfo));
1756
1757       group = ei->group;
1758
1759       xx_group = *group;        /* copy group data into temporary buffer */
1760
1761       setConfigToDefaultsFromConfigList(chunk_config_GRPX);
1762
1763       *group = xx_group;
1764     }
1765   }
1766
1767   clipboard_elements_initialized = TRUE;
1768 }
1769
1770 static void setLevelInfoToDefaults(struct LevelInfo *level,
1771                                    boolean level_info_only)
1772 {
1773   setLevelInfoToDefaults_Level(level);
1774
1775   if (!level_info_only)
1776     setLevelInfoToDefaults_Elements(level);
1777
1778   level->no_valid_file = FALSE;
1779
1780   level->changed = FALSE;
1781 }
1782
1783 #else
1784
1785 static void setLevelInfoToDefaults(struct LevelInfo *level,
1786                                    boolean level_info_only)
1787 {
1788   static boolean clipboard_elements_initialized = FALSE;
1789   int i, x, y;
1790
1791   if (level_info_only)
1792     return;
1793
1794   InitElementPropertiesStatic();
1795
1796   li = *level;          /* copy level data into temporary buffer */
1797
1798   setConfigToDefaultsFromConfigList(chunk_config_INFO);
1799   setConfigToDefaultsFromConfigList(chunk_config_ELEM);
1800
1801   *level = li;          /* copy temporary buffer back to level data */
1802
1803   setLevelInfoToDefaults_EM();
1804   setLevelInfoToDefaults_SP();
1805
1806   level->native_em_level = &native_em_level;
1807   level->native_sp_level = &native_sp_level;
1808
1809   level->file_version = FILE_VERSION_ACTUAL;
1810   level->game_version = GAME_VERSION_ACTUAL;
1811
1812   level->creation_date = getCurrentDate();
1813
1814   level->encoding_16bit_field  = TRUE;
1815   level->encoding_16bit_yamyam = TRUE;
1816   level->encoding_16bit_amoeba = TRUE;
1817
1818   for (x = 0; x < MAX_LEV_FIELDX; x++)
1819     for (y = 0; y < MAX_LEV_FIELDY; y++)
1820       level->field[x][y] = EL_SAND;
1821
1822   for (i = 0; i < MAX_LEVEL_NAME_LEN; i++)
1823     level->name[i] = '\0';
1824   for (i = 0; i < MAX_LEVEL_AUTHOR_LEN; i++)
1825     level->author[i] = '\0';
1826
1827   strcpy(level->name, NAMELESS_LEVEL_NAME);
1828   strcpy(level->author, ANONYMOUS_NAME);
1829
1830   level->field[0][0] = EL_PLAYER_1;
1831   level->field[STD_LEV_FIELDX - 1][STD_LEV_FIELDY - 1] = EL_EXIT_CLOSED;
1832
1833   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
1834   {
1835     int element = i;
1836     struct ElementInfo *ei = &element_info[element];
1837
1838     /* never initialize clipboard elements after the very first time */
1839     /* (to be able to use clipboard elements between several levels) */
1840     if (IS_CLIPBOARD_ELEMENT(element) && clipboard_elements_initialized)
1841       continue;
1842
1843     if (IS_ENVELOPE(element))
1844     {
1845       int envelope_nr = element - EL_ENVELOPE_1;
1846
1847       setConfigToDefaultsFromConfigList(chunk_config_NOTE);
1848
1849       level->envelope[envelope_nr] = xx_envelope;
1850     }
1851
1852     if (IS_CUSTOM_ELEMENT(element) ||
1853         IS_GROUP_ELEMENT(element) ||
1854         IS_INTERNAL_ELEMENT(element))
1855     {
1856       xx_ei = *ei;      /* copy element data into temporary buffer */
1857
1858       setConfigToDefaultsFromConfigList(chunk_config_CUSX_base);
1859
1860       *ei = xx_ei;
1861     }
1862
1863     setElementChangePages(ei, 1);
1864     setElementChangeInfoToDefaults(ei->change);
1865
1866     if (IS_CUSTOM_ELEMENT(element) ||
1867         IS_GROUP_ELEMENT(element) ||
1868         IS_INTERNAL_ELEMENT(element))
1869     {
1870       setElementDescriptionToDefault(ei);
1871
1872       ei->modified_settings = FALSE;
1873     }
1874
1875     if (IS_CUSTOM_ELEMENT(element) ||
1876         IS_INTERNAL_ELEMENT(element))
1877     {
1878       /* internal values used in level editor */
1879
1880       ei->access_type = 0;
1881       ei->access_layer = 0;
1882       ei->access_protected = 0;
1883       ei->walk_to_action = 0;
1884       ei->smash_targets = 0;
1885       ei->deadliness = 0;
1886
1887       ei->can_explode_by_fire = FALSE;
1888       ei->can_explode_smashed = FALSE;
1889       ei->can_explode_impact = FALSE;
1890
1891       ei->current_change_page = 0;
1892     }
1893
1894     if (IS_GROUP_ELEMENT(element) ||
1895         IS_INTERNAL_ELEMENT(element))
1896     {
1897       struct ElementGroupInfo *group;
1898
1899       /* initialize memory for list of elements in group */
1900       if (ei->group == NULL)
1901         ei->group = checked_malloc(sizeof(struct ElementGroupInfo));
1902
1903       group = ei->group;
1904
1905       xx_group = *group;        /* copy group data into temporary buffer */
1906
1907       setConfigToDefaultsFromConfigList(chunk_config_GRPX);
1908
1909       *group = xx_group;
1910     }
1911   }
1912
1913   clipboard_elements_initialized = TRUE;
1914
1915   BorderElement = EL_STEELWALL;
1916
1917   level->no_valid_file = FALSE;
1918
1919   level->changed = FALSE;
1920
1921   /* set all bug compatibility flags to "false" => do not emulate this bug */
1922   level->use_action_after_change_bug = FALSE;
1923
1924   if (leveldir_current)
1925   {
1926     /* try to determine better author name than 'anonymous' */
1927     if (!strEqual(leveldir_current->author, ANONYMOUS_NAME))
1928     {
1929       strncpy(level->author, leveldir_current->author, MAX_LEVEL_AUTHOR_LEN);
1930       level->author[MAX_LEVEL_AUTHOR_LEN] = '\0';
1931     }
1932     else
1933     {
1934       switch (LEVELCLASS(leveldir_current))
1935       {
1936         case LEVELCLASS_TUTORIAL:
1937           strcpy(level->author, PROGRAM_AUTHOR_STRING);
1938           break;
1939
1940         case LEVELCLASS_CONTRIB:
1941           strncpy(level->author, leveldir_current->name, MAX_LEVEL_AUTHOR_LEN);
1942           level->author[MAX_LEVEL_AUTHOR_LEN] = '\0';
1943           break;
1944
1945         case LEVELCLASS_PRIVATE:
1946           strncpy(level->author, getRealName(), MAX_LEVEL_AUTHOR_LEN);
1947           level->author[MAX_LEVEL_AUTHOR_LEN] = '\0';
1948           break;
1949
1950         default:
1951           /* keep default value */
1952           break;
1953       }
1954     }
1955   }
1956 }
1957
1958 #endif
1959
1960 static void setFileInfoToDefaults(struct LevelFileInfo *level_file_info)
1961 {
1962   level_file_info->nr = 0;
1963   level_file_info->type = LEVEL_FILE_TYPE_UNKNOWN;
1964   level_file_info->packed = FALSE;
1965   level_file_info->basename = NULL;
1966   level_file_info->filename = NULL;
1967 }
1968
1969 static void ActivateLevelTemplate()
1970 {
1971   int x, y;
1972
1973   /* Currently there is no special action needed to activate the template
1974      data, because 'element_info' property settings overwrite the original
1975      level data, while all other variables do not change. */
1976
1977   /* Exception: 'from_level_template' elements in the original level playfield
1978      are overwritten with the corresponding elements at the same position in
1979      playfield from the level template. */
1980
1981   for (x = 0; x < level.fieldx; x++)
1982     for (y = 0; y < level.fieldy; y++)
1983       if (level.field[x][y] == EL_FROM_LEVEL_TEMPLATE)
1984         level.field[x][y] = level_template.field[x][y];
1985
1986   if (check_special_flags("load_xsb_to_ces"))
1987   {
1988     struct LevelInfo level_backup = level;
1989
1990     /* overwrite all individual level settings from template level settings */
1991     level = level_template;
1992
1993     /* restore playfield size */
1994     level.fieldx = level_backup.fieldx;
1995     level.fieldy = level_backup.fieldy;
1996
1997     /* restore playfield content */
1998     for (x = 0; x < level.fieldx; x++)
1999       for (y = 0; y < level.fieldy; y++)
2000         level.field[x][y] = level_backup.field[x][y];
2001
2002     /* restore name and author from individual level */
2003     strcpy(level.name,   level_backup.name);
2004     strcpy(level.author, level_backup.author);
2005
2006     /* restore flag "use_custom_template" */
2007     level.use_custom_template = level_backup.use_custom_template;
2008   }
2009 }
2010
2011 static char *getLevelFilenameFromBasename(char *basename)
2012 {
2013   static char *filename = NULL;
2014
2015   checked_free(filename);
2016
2017   filename = getPath2(getCurrentLevelDir(), basename);
2018
2019   return filename;
2020 }
2021
2022 static int getFileTypeFromBasename(char *basename)
2023 {
2024   /* !!! ALSO SEE COMMENT IN checkForPackageFromBasename() !!! */
2025
2026   static char *filename = NULL;
2027   struct stat file_status;
2028
2029   /* ---------- try to determine file type from filename ---------- */
2030
2031   /* check for typical filename of a Supaplex level package file */
2032 #if 1
2033   if (strlen(basename) == 10 && strPrefixLower(basename, "levels.d"))
2034     return LEVEL_FILE_TYPE_SP;
2035 #else
2036   if (strlen(basename) == 10 && (strncmp(basename, "levels.d", 8) == 0 ||
2037                                  strncmp(basename, "LEVELS.D", 8) == 0))
2038     return LEVEL_FILE_TYPE_SP;
2039 #endif
2040
2041   /* check for typical filename of a Diamond Caves II level package file */
2042   if (strSuffixLower(basename, ".dc") ||
2043       strSuffixLower(basename, ".dc2"))
2044     return LEVEL_FILE_TYPE_DC;
2045
2046   /* check for typical filename of a Sokoban level package file */
2047   if (strSuffixLower(basename, ".xsb") &&
2048       strchr(basename, '%') == NULL)
2049     return LEVEL_FILE_TYPE_SB;
2050
2051   /* ---------- try to determine file type from filesize ---------- */
2052
2053   checked_free(filename);
2054   filename = getPath2(getCurrentLevelDir(), basename);
2055
2056   if (stat(filename, &file_status) == 0)
2057   {
2058     /* check for typical filesize of a Supaplex level package file */
2059     if (file_status.st_size == 170496)
2060       return LEVEL_FILE_TYPE_SP;
2061   }
2062
2063   return LEVEL_FILE_TYPE_UNKNOWN;
2064 }
2065
2066 static boolean checkForPackageFromBasename(char *basename)
2067 {
2068   /* !!! WON'T WORK ANYMORE IF getFileTypeFromBasename() ALSO DETECTS !!!
2069      !!! SINGLE LEVELS (CURRENTLY ONLY DETECTS LEVEL PACKAGES         !!! */
2070
2071   return (getFileTypeFromBasename(basename) != LEVEL_FILE_TYPE_UNKNOWN);
2072 }
2073
2074 static char *getSingleLevelBasenameExt(int nr, char *extension)
2075 {
2076   static char basename[MAX_FILENAME_LEN];
2077
2078   if (nr < 0)
2079     sprintf(basename, "template.%s", extension);
2080   else
2081     sprintf(basename, "%03d.%s", nr, extension);
2082
2083   return basename;
2084 }
2085
2086 static char *getSingleLevelBasename(int nr)
2087 {
2088   return getSingleLevelBasenameExt(nr, LEVELFILE_EXTENSION);
2089 }
2090
2091 #if 1
2092
2093 static char *getPackedLevelBasename(int type)
2094 {
2095   static char basename[MAX_FILENAME_LEN];
2096   char *directory = getCurrentLevelDir();
2097   Directory *dir;
2098   DirectoryEntry *dir_entry;
2099
2100   strcpy(basename, UNDEFINED_FILENAME);         /* default: undefined file */
2101
2102   if ((dir = openDirectory(directory)) == NULL)
2103   {
2104     Error(ERR_WARN, "cannot read current level directory '%s'", directory);
2105
2106     return basename;
2107   }
2108
2109   while ((dir_entry = readDirectory(dir)) != NULL)      /* loop all entries */
2110   {
2111     char *entry_basename = dir_entry->basename;
2112     int entry_type = getFileTypeFromBasename(entry_basename);
2113
2114     if (entry_type != LEVEL_FILE_TYPE_UNKNOWN)  /* found valid level package */
2115     {
2116       if (type == LEVEL_FILE_TYPE_UNKNOWN ||
2117           type == entry_type)
2118       {
2119         strcpy(basename, entry_basename);
2120
2121         break;
2122       }
2123     }
2124   }
2125
2126   closeDirectory(dir);
2127
2128   return basename;
2129 }
2130
2131 #else
2132
2133 static char *getPackedLevelBasename(int type)
2134 {
2135   static char basename[MAX_FILENAME_LEN];
2136   char *directory = getCurrentLevelDir();
2137   DIR *dir;
2138   struct dirent *dir_entry;
2139
2140   strcpy(basename, UNDEFINED_FILENAME);         /* default: undefined file */
2141
2142   if ((dir = opendir(directory)) == NULL)
2143   {
2144     Error(ERR_WARN, "cannot read current level directory '%s'", directory);
2145
2146     return basename;
2147   }
2148
2149   while ((dir_entry = readdir(dir)) != NULL)    /* loop until last dir entry */
2150   {
2151     char *entry_basename = dir_entry->d_name;
2152     int entry_type = getFileTypeFromBasename(entry_basename);
2153
2154     if (entry_type != LEVEL_FILE_TYPE_UNKNOWN)  /* found valid level package */
2155     {
2156       if (type == LEVEL_FILE_TYPE_UNKNOWN ||
2157           type == entry_type)
2158       {
2159         strcpy(basename, entry_basename);
2160
2161         break;
2162       }
2163     }
2164   }
2165
2166   closedir(dir);
2167
2168   return basename;
2169 }
2170
2171 #endif
2172
2173 static char *getSingleLevelFilename(int nr)
2174 {
2175   return getLevelFilenameFromBasename(getSingleLevelBasename(nr));
2176 }
2177
2178 #if 0
2179 static char *getPackedLevelFilename(int type)
2180 {
2181   return getLevelFilenameFromBasename(getPackedLevelBasename(type));
2182 }
2183 #endif
2184
2185 char *getDefaultLevelFilename(int nr)
2186 {
2187   return getSingleLevelFilename(nr);
2188 }
2189
2190 #if 0
2191 static void setLevelFileInfo_SingleLevelFilename(struct LevelFileInfo *lfi,
2192                                                  int type)
2193 {
2194   lfi->type = type;
2195   lfi->packed = FALSE;
2196   lfi->basename = getSingleLevelBasename(lfi->nr, lfi->type);
2197   lfi->filename = getLevelFilenameFromBasename(lfi->basename);
2198 }
2199 #endif
2200
2201 static void setLevelFileInfo_FormatLevelFilename(struct LevelFileInfo *lfi,
2202                                                  int type, char *format, ...)
2203 {
2204   static char basename[MAX_FILENAME_LEN];
2205   va_list ap;
2206
2207   va_start(ap, format);
2208   vsprintf(basename, format, ap);
2209   va_end(ap);
2210
2211   lfi->type = type;
2212   lfi->packed = FALSE;
2213   lfi->basename = basename;
2214   lfi->filename = getLevelFilenameFromBasename(lfi->basename);
2215 }
2216
2217 static void setLevelFileInfo_PackedLevelFilename(struct LevelFileInfo *lfi,
2218                                                  int type)
2219 {
2220   lfi->type = type;
2221   lfi->packed = TRUE;
2222   lfi->basename = getPackedLevelBasename(lfi->type);
2223   lfi->filename = getLevelFilenameFromBasename(lfi->basename);
2224 }
2225
2226 static int getFiletypeFromID(char *filetype_id)
2227 {
2228   char *filetype_id_lower;
2229   int filetype = LEVEL_FILE_TYPE_UNKNOWN;
2230   int i;
2231
2232   if (filetype_id == NULL)
2233     return LEVEL_FILE_TYPE_UNKNOWN;
2234
2235   filetype_id_lower = getStringToLower(filetype_id);
2236
2237   for (i = 0; filetype_id_list[i].id != NULL; i++)
2238   {
2239     char *id_lower = getStringToLower(filetype_id_list[i].id);
2240     
2241     if (strEqual(filetype_id_lower, id_lower))
2242       filetype = filetype_id_list[i].filetype;
2243
2244     free(id_lower);
2245
2246     if (filetype != LEVEL_FILE_TYPE_UNKNOWN)
2247       break;
2248   }
2249
2250   free(filetype_id_lower);
2251
2252   return filetype;
2253 }
2254
2255 static void determineLevelFileInfo_Filename(struct LevelFileInfo *lfi)
2256 {
2257   int nr = lfi->nr;
2258
2259   /* special case: level number is negative => check for level template file */
2260   if (nr < 0)
2261   {
2262 #if 1
2263     /* global variable "leveldir_current" must be modified in the loop below */
2264     LevelDirTree *leveldir_current_last = leveldir_current;
2265
2266     /* check for template level in path from current to topmost tree node */
2267
2268     while (leveldir_current != NULL)
2269     {
2270       setLevelFileInfo_FormatLevelFilename(lfi, LEVEL_FILE_TYPE_RND,
2271                                            "template.%s", LEVELFILE_EXTENSION);
2272
2273       if (fileExists(lfi->filename))
2274         break;
2275
2276       leveldir_current = leveldir_current->node_parent;
2277     }
2278
2279     /* restore global variable "leveldir_current" modified in above loop */
2280     leveldir_current = leveldir_current_last;
2281
2282 #else
2283
2284     setLevelFileInfo_FormatLevelFilename(lfi, LEVEL_FILE_TYPE_RND,
2285                                          "template.%s", LEVELFILE_EXTENSION);
2286
2287 #endif
2288
2289     /* no fallback if template file not existing */
2290     return;
2291   }
2292
2293   /* special case: check for file name/pattern specified in "levelinfo.conf" */
2294   if (leveldir_current->level_filename != NULL)
2295   {
2296     int filetype = getFiletypeFromID(leveldir_current->level_filetype);
2297
2298     setLevelFileInfo_FormatLevelFilename(lfi, filetype,
2299                                          leveldir_current->level_filename, nr);
2300
2301     lfi->packed = checkForPackageFromBasename(leveldir_current->level_filename);
2302
2303     if (fileExists(lfi->filename))
2304       return;
2305   }
2306
2307   /* check for native Rocks'n'Diamonds level file */
2308   setLevelFileInfo_FormatLevelFilename(lfi, LEVEL_FILE_TYPE_RND,
2309                                        "%03d.%s", nr, LEVELFILE_EXTENSION);
2310   if (fileExists(lfi->filename))
2311     return;
2312
2313   /* check for Emerald Mine level file (V1) */
2314   setLevelFileInfo_FormatLevelFilename(lfi, LEVEL_FILE_TYPE_EM, "a%c%c",
2315                                        'a' + (nr / 10) % 26, '0' + nr % 10);
2316   if (fileExists(lfi->filename))
2317     return;
2318   setLevelFileInfo_FormatLevelFilename(lfi, LEVEL_FILE_TYPE_EM, "A%c%c",
2319                                        'A' + (nr / 10) % 26, '0' + nr % 10);
2320   if (fileExists(lfi->filename))
2321     return;
2322
2323   /* check for Emerald Mine level file (V2 to V5) */
2324   setLevelFileInfo_FormatLevelFilename(lfi, LEVEL_FILE_TYPE_EM, "%d", nr);
2325   if (fileExists(lfi->filename))
2326     return;
2327
2328   /* check for Emerald Mine level file (V6 / single mode) */
2329   setLevelFileInfo_FormatLevelFilename(lfi, LEVEL_FILE_TYPE_EM, "%02ds", nr);
2330   if (fileExists(lfi->filename))
2331     return;
2332   setLevelFileInfo_FormatLevelFilename(lfi, LEVEL_FILE_TYPE_EM, "%02dS", nr);
2333   if (fileExists(lfi->filename))
2334     return;
2335
2336   /* check for Emerald Mine level file (V6 / teamwork mode) */
2337   setLevelFileInfo_FormatLevelFilename(lfi, LEVEL_FILE_TYPE_EM, "%02dt", nr);
2338   if (fileExists(lfi->filename))
2339     return;
2340   setLevelFileInfo_FormatLevelFilename(lfi, LEVEL_FILE_TYPE_EM, "%02dT", nr);
2341   if (fileExists(lfi->filename))
2342     return;
2343
2344   /* check for various packed level file formats */
2345   setLevelFileInfo_PackedLevelFilename(lfi, LEVEL_FILE_TYPE_UNKNOWN);
2346   if (fileExists(lfi->filename))
2347     return;
2348
2349   /* no known level file found -- use default values (and fail later) */
2350   setLevelFileInfo_FormatLevelFilename(lfi, LEVEL_FILE_TYPE_RND,
2351                                        "%03d.%s", nr, LEVELFILE_EXTENSION);
2352 }
2353
2354 static void determineLevelFileInfo_Filetype(struct LevelFileInfo *lfi)
2355 {
2356   if (lfi->type == LEVEL_FILE_TYPE_UNKNOWN)
2357     lfi->type = getFileTypeFromBasename(lfi->basename);
2358 }
2359
2360 static void setLevelFileInfo(struct LevelFileInfo *level_file_info, int nr)
2361 {
2362   /* always start with reliable default values */
2363   setFileInfoToDefaults(level_file_info);
2364
2365   level_file_info->nr = nr;     /* set requested level number */
2366
2367   determineLevelFileInfo_Filename(level_file_info);
2368   determineLevelFileInfo_Filetype(level_file_info);
2369 }
2370
2371 /* ------------------------------------------------------------------------- */
2372 /* functions for loading R'n'D level                                         */
2373 /* ------------------------------------------------------------------------- */
2374
2375 int getMappedElement(int element)
2376 {
2377   /* remap some (historic, now obsolete) elements */
2378
2379   switch (element)
2380   {
2381     case EL_PLAYER_OBSOLETE:
2382       element = EL_PLAYER_1;
2383       break;
2384
2385     case EL_KEY_OBSOLETE:
2386       element = EL_KEY_1;
2387       break;
2388
2389     case EL_EM_KEY_1_FILE_OBSOLETE:
2390       element = EL_EM_KEY_1;
2391       break;
2392
2393     case EL_EM_KEY_2_FILE_OBSOLETE:
2394       element = EL_EM_KEY_2;
2395       break;
2396
2397     case EL_EM_KEY_3_FILE_OBSOLETE:
2398       element = EL_EM_KEY_3;
2399       break;
2400
2401     case EL_EM_KEY_4_FILE_OBSOLETE:
2402       element = EL_EM_KEY_4;
2403       break;
2404
2405     case EL_ENVELOPE_OBSOLETE:
2406       element = EL_ENVELOPE_1;
2407       break;
2408
2409     case EL_SP_EMPTY:
2410       element = EL_EMPTY;
2411       break;
2412
2413     default:
2414       if (element >= NUM_FILE_ELEMENTS)
2415       {
2416         Error(ERR_WARN, "invalid level element %d", element);
2417
2418         element = EL_UNKNOWN;
2419       }
2420       break;
2421   }
2422
2423   return element;
2424 }
2425
2426 int getMappedElementByVersion(int element, int game_version)
2427 {
2428   /* remap some elements due to certain game version */
2429
2430   if (game_version <= VERSION_IDENT(2,2,0,0))
2431   {
2432     /* map game font elements */
2433     element = (element == EL_CHAR('[')  ? EL_CHAR_AUMLAUT :
2434                element == EL_CHAR('\\') ? EL_CHAR_OUMLAUT :
2435                element == EL_CHAR(']')  ? EL_CHAR_UUMLAUT :
2436                element == EL_CHAR('^')  ? EL_CHAR_COPYRIGHT : element);
2437   }
2438
2439   if (game_version < VERSION_IDENT(3,0,0,0))
2440   {
2441     /* map Supaplex gravity tube elements */
2442     element = (element == EL_SP_GRAVITY_PORT_LEFT  ? EL_SP_PORT_LEFT  :
2443                element == EL_SP_GRAVITY_PORT_RIGHT ? EL_SP_PORT_RIGHT :
2444                element == EL_SP_GRAVITY_PORT_UP    ? EL_SP_PORT_UP    :
2445                element == EL_SP_GRAVITY_PORT_DOWN  ? EL_SP_PORT_DOWN  :
2446                element);
2447   }
2448
2449   return element;
2450 }
2451
2452 #if 1
2453
2454 static int LoadLevel_VERS(File *file, int chunk_size, struct LevelInfo *level)
2455 {
2456   level->file_version = getFileVersion(file);
2457   level->game_version = getFileVersion(file);
2458
2459   return chunk_size;
2460 }
2461
2462 static int LoadLevel_DATE(File *file, int chunk_size, struct LevelInfo *level)
2463 {
2464   level->creation_date.year  = getFile16BitBE(file);
2465   level->creation_date.month = getFile8Bit(file);
2466   level->creation_date.day   = getFile8Bit(file);
2467
2468   level->creation_date.src   = DATE_SRC_LEVELFILE;
2469
2470   return chunk_size;
2471 }
2472
2473 static int LoadLevel_HEAD(File *file, int chunk_size, struct LevelInfo *level)
2474 {
2475   int initial_player_stepsize;
2476   int initial_player_gravity;
2477   int i, x, y;
2478
2479   level->fieldx = getFile8Bit(file);
2480   level->fieldy = getFile8Bit(file);
2481
2482   level->time           = getFile16BitBE(file);
2483   level->gems_needed    = getFile16BitBE(file);
2484
2485   for (i = 0; i < MAX_LEVEL_NAME_LEN; i++)
2486     level->name[i] = getFile8Bit(file);
2487   level->name[MAX_LEVEL_NAME_LEN] = 0;
2488
2489   for (i = 0; i < LEVEL_SCORE_ELEMENTS; i++)
2490     level->score[i] = getFile8Bit(file);
2491
2492   level->num_yamyam_contents = STD_ELEMENT_CONTENTS;
2493   for (i = 0; i < STD_ELEMENT_CONTENTS; i++)
2494     for (y = 0; y < 3; y++)
2495       for (x = 0; x < 3; x++)
2496         level->yamyam_content[i].e[x][y] = getMappedElement(getFile8Bit(file));
2497
2498   level->amoeba_speed           = getFile8Bit(file);
2499   level->time_magic_wall        = getFile8Bit(file);
2500   level->time_wheel             = getFile8Bit(file);
2501   level->amoeba_content         = getMappedElement(getFile8Bit(file));
2502
2503   initial_player_stepsize       = (getFile8Bit(file) == 1 ? STEPSIZE_FAST :
2504                                    STEPSIZE_NORMAL);
2505
2506   for (i = 0; i < MAX_PLAYERS; i++)
2507     level->initial_player_stepsize[i] = initial_player_stepsize;
2508
2509   initial_player_gravity        = (getFile8Bit(file) == 1 ? TRUE : FALSE);
2510
2511   for (i = 0; i < MAX_PLAYERS; i++)
2512     level->initial_player_gravity[i] = initial_player_gravity;
2513
2514   level->encoding_16bit_field   = (getFile8Bit(file) == 1 ? TRUE : FALSE);
2515   level->em_slippery_gems       = (getFile8Bit(file) == 1 ? TRUE : FALSE);
2516
2517   level->use_custom_template    = (getFile8Bit(file) == 1 ? TRUE : FALSE);
2518
2519   level->block_last_field       = (getFile8Bit(file) == 1 ? TRUE : FALSE);
2520   level->sp_block_last_field    = (getFile8Bit(file) == 1 ? TRUE : FALSE);
2521   level->can_move_into_acid_bits = getFile32BitBE(file);
2522   level->dont_collide_with_bits = getFile8Bit(file);
2523
2524   level->use_spring_bug         = (getFile8Bit(file) == 1 ? TRUE : FALSE);
2525   level->use_step_counter       = (getFile8Bit(file) == 1 ? TRUE : FALSE);
2526
2527   level->instant_relocation     = (getFile8Bit(file) == 1 ? TRUE : FALSE);
2528   level->can_pass_to_walkable   = (getFile8Bit(file) == 1 ? TRUE : FALSE);
2529   level->grow_into_diggable     = (getFile8Bit(file) == 1 ? TRUE : FALSE);
2530
2531   level->game_engine_type       = getFile8Bit(file);
2532
2533   ReadUnusedBytesFromFile(file, LEVEL_CHUNK_HEAD_UNUSED);
2534
2535   return chunk_size;
2536 }
2537
2538 static int LoadLevel_NAME(File *file, int chunk_size, struct LevelInfo *level)
2539 {
2540   int i;
2541
2542   for (i = 0; i < MAX_LEVEL_NAME_LEN; i++)
2543     level->name[i] = getFile8Bit(file);
2544   level->name[MAX_LEVEL_NAME_LEN] = 0;
2545
2546   return chunk_size;
2547 }
2548
2549 static int LoadLevel_AUTH(File *file, int chunk_size, struct LevelInfo *level)
2550 {
2551   int i;
2552
2553   for (i = 0; i < MAX_LEVEL_AUTHOR_LEN; i++)
2554     level->author[i] = getFile8Bit(file);
2555   level->author[MAX_LEVEL_AUTHOR_LEN] = 0;
2556
2557   return chunk_size;
2558 }
2559
2560 static int LoadLevel_BODY(File *file, int chunk_size, struct LevelInfo *level)
2561 {
2562   int x, y;
2563   int chunk_size_expected = level->fieldx * level->fieldy;
2564
2565   /* Note: "chunk_size" was wrong before version 2.0 when elements are
2566      stored with 16-bit encoding (and should be twice as big then).
2567      Even worse, playfield data was stored 16-bit when only yamyam content
2568      contained 16-bit elements and vice versa. */
2569
2570   if (level->encoding_16bit_field && level->file_version >= FILE_VERSION_2_0)
2571     chunk_size_expected *= 2;
2572
2573   if (chunk_size_expected != chunk_size)
2574   {
2575     ReadUnusedBytesFromFile(file, chunk_size);
2576     return chunk_size_expected;
2577   }
2578
2579   for (y = 0; y < level->fieldy; y++)
2580     for (x = 0; x < level->fieldx; x++)
2581       level->field[x][y] =
2582         getMappedElement(level->encoding_16bit_field ? getFile16BitBE(file) :
2583                          getFile8Bit(file));
2584   return chunk_size;
2585 }
2586
2587 static int LoadLevel_CONT(File *file, int chunk_size, struct LevelInfo *level)
2588 {
2589   int i, x, y;
2590   int header_size = 4;
2591   int content_size = MAX_ELEMENT_CONTENTS * 3 * 3;
2592   int chunk_size_expected = header_size + content_size;
2593
2594   /* Note: "chunk_size" was wrong before version 2.0 when elements are
2595      stored with 16-bit encoding (and should be twice as big then).
2596      Even worse, playfield data was stored 16-bit when only yamyam content
2597      contained 16-bit elements and vice versa. */
2598
2599   if (level->encoding_16bit_field && level->file_version >= FILE_VERSION_2_0)
2600     chunk_size_expected += content_size;
2601
2602   if (chunk_size_expected != chunk_size)
2603   {
2604     ReadUnusedBytesFromFile(file, chunk_size);
2605     return chunk_size_expected;
2606   }
2607
2608   getFile8Bit(file);
2609   level->num_yamyam_contents = getFile8Bit(file);
2610   getFile8Bit(file);
2611   getFile8Bit(file);
2612
2613   /* correct invalid number of content fields -- should never happen */
2614   if (level->num_yamyam_contents < 1 ||
2615       level->num_yamyam_contents > MAX_ELEMENT_CONTENTS)
2616     level->num_yamyam_contents = STD_ELEMENT_CONTENTS;
2617
2618   for (i = 0; i < MAX_ELEMENT_CONTENTS; i++)
2619     for (y = 0; y < 3; y++)
2620       for (x = 0; x < 3; x++)
2621         level->yamyam_content[i].e[x][y] =
2622           getMappedElement(level->encoding_16bit_field ?
2623                            getFile16BitBE(file) : getFile8Bit(file));
2624   return chunk_size;
2625 }
2626
2627 static int LoadLevel_CNT2(File *file, int chunk_size, struct LevelInfo *level)
2628 {
2629   int i, x, y;
2630   int element;
2631   int num_contents;
2632 #if 0
2633   int content_xsize, content_ysize;
2634 #endif
2635   int content_array[MAX_ELEMENT_CONTENTS][3][3];
2636
2637   element = getMappedElement(getFile16BitBE(file));
2638   num_contents = getFile8Bit(file);
2639 #if 1
2640   getFile8Bit(file);    /* content x size (unused) */
2641   getFile8Bit(file);    /* content y size (unused) */
2642 #else
2643   content_xsize = getFile8Bit(file);
2644   content_ysize = getFile8Bit(file);
2645 #endif
2646
2647   ReadUnusedBytesFromFile(file, LEVEL_CHUNK_CNT2_UNUSED);
2648
2649   for (i = 0; i < MAX_ELEMENT_CONTENTS; i++)
2650     for (y = 0; y < 3; y++)
2651       for (x = 0; x < 3; x++)
2652         content_array[i][x][y] = getMappedElement(getFile16BitBE(file));
2653
2654   /* correct invalid number of content fields -- should never happen */
2655   if (num_contents < 1 || num_contents > MAX_ELEMENT_CONTENTS)
2656     num_contents = STD_ELEMENT_CONTENTS;
2657
2658   if (element == EL_YAMYAM)
2659   {
2660     level->num_yamyam_contents = num_contents;
2661
2662     for (i = 0; i < num_contents; i++)
2663       for (y = 0; y < 3; y++)
2664         for (x = 0; x < 3; x++)
2665           level->yamyam_content[i].e[x][y] = content_array[i][x][y];
2666   }
2667   else if (element == EL_BD_AMOEBA)
2668   {
2669     level->amoeba_content = content_array[0][0][0];
2670   }
2671   else
2672   {
2673     Error(ERR_WARN, "cannot load content for element '%d'", element);
2674   }
2675
2676   return chunk_size;
2677 }
2678
2679 static int LoadLevel_CNT3(File *file, int chunk_size, struct LevelInfo *level)
2680 {
2681   int i;
2682   int element;
2683   int envelope_nr;
2684   int envelope_len;
2685   int chunk_size_expected;
2686
2687   element = getMappedElement(getFile16BitBE(file));
2688   if (!IS_ENVELOPE(element))
2689     element = EL_ENVELOPE_1;
2690
2691   envelope_nr = element - EL_ENVELOPE_1;
2692
2693   envelope_len = getFile16BitBE(file);
2694
2695   level->envelope[envelope_nr].xsize = getFile8Bit(file);
2696   level->envelope[envelope_nr].ysize = getFile8Bit(file);
2697
2698   ReadUnusedBytesFromFile(file, LEVEL_CHUNK_CNT3_UNUSED);
2699
2700   chunk_size_expected = LEVEL_CHUNK_CNT3_SIZE(envelope_len);
2701   if (chunk_size_expected != chunk_size)
2702   {
2703     ReadUnusedBytesFromFile(file, chunk_size - LEVEL_CHUNK_CNT3_HEADER);
2704     return chunk_size_expected;
2705   }
2706
2707   for (i = 0; i < envelope_len; i++)
2708     level->envelope[envelope_nr].text[i] = getFile8Bit(file);
2709
2710   return chunk_size;
2711 }
2712
2713 static int LoadLevel_CUS1(File *file, int chunk_size, struct LevelInfo *level)
2714 {
2715   int num_changed_custom_elements = getFile16BitBE(file);
2716   int chunk_size_expected = 2 + num_changed_custom_elements * 6;
2717   int i;
2718
2719   if (chunk_size_expected != chunk_size)
2720   {
2721     ReadUnusedBytesFromFile(file, chunk_size - 2);
2722     return chunk_size_expected;
2723   }
2724
2725   for (i = 0; i < num_changed_custom_elements; i++)
2726   {
2727     int element = getMappedElement(getFile16BitBE(file));
2728     int properties = getFile32BitBE(file);
2729
2730     if (IS_CUSTOM_ELEMENT(element))
2731       element_info[element].properties[EP_BITFIELD_BASE_NR] = properties;
2732     else
2733       Error(ERR_WARN, "invalid custom element number %d", element);
2734
2735     /* older game versions that wrote level files with CUS1 chunks used
2736        different default push delay values (not yet stored in level file) */
2737     element_info[element].push_delay_fixed = 2;
2738     element_info[element].push_delay_random = 8;
2739   }
2740
2741   return chunk_size;
2742 }
2743
2744 static int LoadLevel_CUS2(File *file, int chunk_size, struct LevelInfo *level)
2745 {
2746   int num_changed_custom_elements = getFile16BitBE(file);
2747   int chunk_size_expected = 2 + num_changed_custom_elements * 4;
2748   int i;
2749
2750   if (chunk_size_expected != chunk_size)
2751   {
2752     ReadUnusedBytesFromFile(file, chunk_size - 2);
2753     return chunk_size_expected;
2754   }
2755
2756   for (i = 0; i < num_changed_custom_elements; i++)
2757   {
2758     int element = getMappedElement(getFile16BitBE(file));
2759     int custom_target_element = getMappedElement(getFile16BitBE(file));
2760
2761     if (IS_CUSTOM_ELEMENT(element))
2762       element_info[element].change->target_element = custom_target_element;
2763     else
2764       Error(ERR_WARN, "invalid custom element number %d", element);
2765   }
2766
2767   return chunk_size;
2768 }
2769
2770 static int LoadLevel_CUS3(File *file, int chunk_size, struct LevelInfo *level)
2771 {
2772   int num_changed_custom_elements = getFile16BitBE(file);
2773   int chunk_size_expected = LEVEL_CHUNK_CUS3_SIZE(num_changed_custom_elements);
2774   int i, j, x, y;
2775
2776   if (chunk_size_expected != chunk_size)
2777   {
2778     ReadUnusedBytesFromFile(file, chunk_size - 2);
2779     return chunk_size_expected;
2780   }
2781
2782   for (i = 0; i < num_changed_custom_elements; i++)
2783   {
2784     int element = getMappedElement(getFile16BitBE(file));
2785     struct ElementInfo *ei = &element_info[element];
2786     unsigned int event_bits;
2787
2788     if (!IS_CUSTOM_ELEMENT(element))
2789     {
2790       Error(ERR_WARN, "invalid custom element number %d", element);
2791
2792       element = EL_INTERNAL_DUMMY;
2793     }
2794
2795     for (j = 0; j < MAX_ELEMENT_NAME_LEN; j++)
2796       ei->description[j] = getFile8Bit(file);
2797     ei->description[MAX_ELEMENT_NAME_LEN] = 0;
2798
2799     ei->properties[EP_BITFIELD_BASE_NR] = getFile32BitBE(file);
2800
2801     /* some free bytes for future properties and padding */
2802     ReadUnusedBytesFromFile(file, 7);
2803
2804     ei->use_gfx_element = getFile8Bit(file);
2805     ei->gfx_element_initial = getMappedElement(getFile16BitBE(file));
2806
2807     ei->collect_score_initial = getFile8Bit(file);
2808     ei->collect_count_initial = getFile8Bit(file);
2809
2810     ei->push_delay_fixed = getFile16BitBE(file);
2811     ei->push_delay_random = getFile16BitBE(file);
2812     ei->move_delay_fixed = getFile16BitBE(file);
2813     ei->move_delay_random = getFile16BitBE(file);
2814
2815     ei->move_pattern = getFile16BitBE(file);
2816     ei->move_direction_initial = getFile8Bit(file);
2817     ei->move_stepsize = getFile8Bit(file);
2818
2819     for (y = 0; y < 3; y++)
2820       for (x = 0; x < 3; x++)
2821         ei->content.e[x][y] = getMappedElement(getFile16BitBE(file));
2822
2823     event_bits = getFile32BitBE(file);
2824     for (j = 0; j < NUM_CHANGE_EVENTS; j++)
2825       if (event_bits & (1 << j))
2826         ei->change->has_event[j] = TRUE;
2827
2828     ei->change->target_element = getMappedElement(getFile16BitBE(file));
2829
2830     ei->change->delay_fixed = getFile16BitBE(file);
2831     ei->change->delay_random = getFile16BitBE(file);
2832     ei->change->delay_frames = getFile16BitBE(file);
2833
2834     ei->change->initial_trigger_element= getMappedElement(getFile16BitBE(file));
2835
2836     ei->change->explode = getFile8Bit(file);
2837     ei->change->use_target_content = getFile8Bit(file);
2838     ei->change->only_if_complete = getFile8Bit(file);
2839     ei->change->use_random_replace = getFile8Bit(file);
2840
2841     ei->change->random_percentage = getFile8Bit(file);
2842     ei->change->replace_when = getFile8Bit(file);
2843
2844     for (y = 0; y < 3; y++)
2845       for (x = 0; x < 3; x++)
2846         ei->change->target_content.e[x][y] =
2847           getMappedElement(getFile16BitBE(file));
2848
2849     ei->slippery_type = getFile8Bit(file);
2850
2851     /* some free bytes for future properties and padding */
2852     ReadUnusedBytesFromFile(file, LEVEL_CPART_CUS3_UNUSED);
2853
2854     /* mark that this custom element has been modified */
2855     ei->modified_settings = TRUE;
2856   }
2857
2858   return chunk_size;
2859 }
2860
2861 static int LoadLevel_CUS4(File *file, int chunk_size, struct LevelInfo *level)
2862 {
2863   struct ElementInfo *ei;
2864   int chunk_size_expected;
2865   int element;
2866   int i, j, x, y;
2867
2868   /* ---------- custom element base property values (96 bytes) ------------- */
2869
2870   element = getMappedElement(getFile16BitBE(file));
2871
2872   if (!IS_CUSTOM_ELEMENT(element))
2873   {
2874     Error(ERR_WARN, "invalid custom element number %d", element);
2875
2876     ReadUnusedBytesFromFile(file, chunk_size - 2);
2877     return chunk_size;
2878   }
2879
2880   ei = &element_info[element];
2881
2882   for (i = 0; i < MAX_ELEMENT_NAME_LEN; i++)
2883     ei->description[i] = getFile8Bit(file);
2884   ei->description[MAX_ELEMENT_NAME_LEN] = 0;
2885
2886   ei->properties[EP_BITFIELD_BASE_NR] = getFile32BitBE(file);
2887
2888   ReadUnusedBytesFromFile(file, 4);     /* reserved for more base properties */
2889
2890   ei->num_change_pages = getFile8Bit(file);
2891
2892   chunk_size_expected = LEVEL_CHUNK_CUS4_SIZE(ei->num_change_pages);
2893   if (chunk_size_expected != chunk_size)
2894   {
2895     ReadUnusedBytesFromFile(file, chunk_size - 43);
2896     return chunk_size_expected;
2897   }
2898
2899   ei->ce_value_fixed_initial = getFile16BitBE(file);
2900   ei->ce_value_random_initial = getFile16BitBE(file);
2901   ei->use_last_ce_value = getFile8Bit(file);
2902
2903   ei->use_gfx_element = getFile8Bit(file);
2904   ei->gfx_element_initial = getMappedElement(getFile16BitBE(file));
2905
2906   ei->collect_score_initial = getFile8Bit(file);
2907   ei->collect_count_initial = getFile8Bit(file);
2908
2909   ei->drop_delay_fixed = getFile8Bit(file);
2910   ei->push_delay_fixed = getFile8Bit(file);
2911   ei->drop_delay_random = getFile8Bit(file);
2912   ei->push_delay_random = getFile8Bit(file);
2913   ei->move_delay_fixed = getFile16BitBE(file);
2914   ei->move_delay_random = getFile16BitBE(file);
2915
2916   /* bits 0 - 15 of "move_pattern" ... */
2917   ei->move_pattern = getFile16BitBE(file);
2918   ei->move_direction_initial = getFile8Bit(file);
2919   ei->move_stepsize = getFile8Bit(file);
2920
2921   ei->slippery_type = getFile8Bit(file);
2922
2923   for (y = 0; y < 3; y++)
2924     for (x = 0; x < 3; x++)
2925       ei->content.e[x][y] = getMappedElement(getFile16BitBE(file));
2926
2927   ei->move_enter_element = getMappedElement(getFile16BitBE(file));
2928   ei->move_leave_element = getMappedElement(getFile16BitBE(file));
2929   ei->move_leave_type = getFile8Bit(file);
2930
2931   /* ... bits 16 - 31 of "move_pattern" (not nice, but downward compatible) */
2932   ei->move_pattern |= (getFile16BitBE(file) << 16);
2933
2934   ei->access_direction = getFile8Bit(file);
2935
2936   ei->explosion_delay = getFile8Bit(file);
2937   ei->ignition_delay = getFile8Bit(file);
2938   ei->explosion_type = getFile8Bit(file);
2939
2940   /* some free bytes for future custom property values and padding */
2941   ReadUnusedBytesFromFile(file, 1);
2942
2943   /* ---------- change page property values (48 bytes) --------------------- */
2944
2945   setElementChangePages(ei, ei->num_change_pages);
2946
2947   for (i = 0; i < ei->num_change_pages; i++)
2948   {
2949     struct ElementChangeInfo *change = &ei->change_page[i];
2950     unsigned int event_bits;
2951
2952     /* always start with reliable default values */
2953     setElementChangeInfoToDefaults(change);
2954
2955     /* bits 0 - 31 of "has_event[]" ... */
2956     event_bits = getFile32BitBE(file);
2957     for (j = 0; j < MIN(NUM_CHANGE_EVENTS, 32); j++)
2958       if (event_bits & (1 << j))
2959         change->has_event[j] = TRUE;
2960
2961     change->target_element = getMappedElement(getFile16BitBE(file));
2962
2963     change->delay_fixed = getFile16BitBE(file);
2964     change->delay_random = getFile16BitBE(file);
2965     change->delay_frames = getFile16BitBE(file);
2966
2967     change->initial_trigger_element = getMappedElement(getFile16BitBE(file));
2968
2969     change->explode = getFile8Bit(file);
2970     change->use_target_content = getFile8Bit(file);
2971     change->only_if_complete = getFile8Bit(file);
2972     change->use_random_replace = getFile8Bit(file);
2973
2974     change->random_percentage = getFile8Bit(file);
2975     change->replace_when = getFile8Bit(file);
2976
2977     for (y = 0; y < 3; y++)
2978       for (x = 0; x < 3; x++)
2979         change->target_content.e[x][y]= getMappedElement(getFile16BitBE(file));
2980
2981     change->can_change = getFile8Bit(file);
2982
2983     change->trigger_side = getFile8Bit(file);
2984
2985     change->trigger_player = getFile8Bit(file);
2986     change->trigger_page = getFile8Bit(file);
2987
2988     change->trigger_page = (change->trigger_page == CH_PAGE_ANY_FILE ?
2989                             CH_PAGE_ANY : (1 << change->trigger_page));
2990
2991     change->has_action = getFile8Bit(file);
2992     change->action_type = getFile8Bit(file);
2993     change->action_mode = getFile8Bit(file);
2994     change->action_arg = getFile16BitBE(file);
2995
2996     /* ... bits 32 - 39 of "has_event[]" (not nice, but downward compatible) */
2997     event_bits = getFile8Bit(file);
2998     for (j = 32; j < NUM_CHANGE_EVENTS; j++)
2999       if (event_bits & (1 << (j - 32)))
3000         change->has_event[j] = TRUE;
3001   }
3002
3003   /* mark this custom element as modified */
3004   ei->modified_settings = TRUE;
3005
3006   return chunk_size;
3007 }
3008
3009 static int LoadLevel_GRP1(File *file, int chunk_size, struct LevelInfo *level)
3010 {
3011   struct ElementInfo *ei;
3012   struct ElementGroupInfo *group;
3013   int element;
3014   int i;
3015
3016   element = getMappedElement(getFile16BitBE(file));
3017
3018   if (!IS_GROUP_ELEMENT(element))
3019   {
3020     Error(ERR_WARN, "invalid group element number %d", element);
3021
3022     ReadUnusedBytesFromFile(file, chunk_size - 2);
3023     return chunk_size;
3024   }
3025
3026   ei = &element_info[element];
3027
3028   for (i = 0; i < MAX_ELEMENT_NAME_LEN; i++)
3029     ei->description[i] = getFile8Bit(file);
3030   ei->description[MAX_ELEMENT_NAME_LEN] = 0;
3031
3032   group = element_info[element].group;
3033
3034   group->num_elements = getFile8Bit(file);
3035
3036   ei->use_gfx_element = getFile8Bit(file);
3037   ei->gfx_element_initial = getMappedElement(getFile16BitBE(file));
3038
3039   group->choice_mode = getFile8Bit(file);
3040
3041   /* some free bytes for future values and padding */
3042   ReadUnusedBytesFromFile(file, 3);
3043
3044   for (i = 0; i < MAX_ELEMENTS_IN_GROUP; i++)
3045     group->element[i] = getMappedElement(getFile16BitBE(file));
3046
3047   /* mark this group element as modified */
3048   element_info[element].modified_settings = TRUE;
3049
3050   return chunk_size;
3051 }
3052
3053 static int LoadLevel_MicroChunk(File *file, struct LevelFileConfigInfo *conf,
3054                                 int element, int real_element)
3055 {
3056   int micro_chunk_size = 0;
3057   int conf_type = getFile8Bit(file);
3058   int byte_mask = conf_type & CONF_MASK_BYTES;
3059   boolean element_found = FALSE;
3060   int i;
3061
3062   micro_chunk_size += 1;
3063
3064   if (byte_mask == CONF_MASK_MULTI_BYTES)
3065   {
3066     int num_bytes = getFile16BitBE(file);
3067     byte *buffer = checked_malloc(num_bytes);
3068
3069     ReadBytesFromFile(file, buffer, num_bytes);
3070
3071     for (i = 0; conf[i].data_type != -1; i++)
3072     {
3073       if (conf[i].element == element &&
3074           conf[i].conf_type == conf_type)
3075       {
3076         int data_type = conf[i].data_type;
3077         int num_entities = num_bytes / CONF_ENTITY_NUM_BYTES(data_type);
3078         int max_num_entities = conf[i].max_num_entities;
3079
3080         if (num_entities > max_num_entities)
3081         {
3082           Error(ERR_WARN,
3083                 "truncating number of entities for element %d from %d to %d",
3084                 element, num_entities, max_num_entities);
3085
3086           num_entities = max_num_entities;
3087         }
3088
3089         if (num_entities == 0 && (data_type == TYPE_ELEMENT_LIST ||
3090                                   data_type == TYPE_CONTENT_LIST))
3091         {
3092           /* for element and content lists, zero entities are not allowed */
3093           Error(ERR_WARN, "found empty list of entities for element %d",
3094                 element);
3095
3096           /* do not set "num_entities" here to prevent reading behind buffer */
3097
3098           *(int *)(conf[i].num_entities) = 1;   /* at least one is required */
3099         }
3100         else
3101         {
3102           *(int *)(conf[i].num_entities) = num_entities;
3103         }
3104
3105         element_found = TRUE;
3106
3107         if (data_type == TYPE_STRING)
3108         {
3109           char *string = (char *)(conf[i].value);
3110           int j;
3111
3112           for (j = 0; j < max_num_entities; j++)
3113             string[j] = (j < num_entities ? buffer[j] : '\0');
3114         }
3115         else if (data_type == TYPE_ELEMENT_LIST)
3116         {
3117           int *element_array = (int *)(conf[i].value);
3118           int j;
3119
3120           for (j = 0; j < num_entities; j++)
3121             element_array[j] =
3122               getMappedElement(CONF_ELEMENTS_ELEMENT(buffer, j));
3123         }
3124         else if (data_type == TYPE_CONTENT_LIST)
3125         {
3126           struct Content *content= (struct Content *)(conf[i].value);
3127           int c, x, y;
3128
3129           for (c = 0; c < num_entities; c++)
3130             for (y = 0; y < 3; y++)
3131               for (x = 0; x < 3; x++)
3132                 content[c].e[x][y] =
3133                   getMappedElement(CONF_CONTENTS_ELEMENT(buffer, c, x, y));
3134         }
3135         else
3136           element_found = FALSE;
3137
3138         break;
3139       }
3140     }
3141
3142     checked_free(buffer);
3143
3144     micro_chunk_size += 2 + num_bytes;
3145   }
3146   else          /* constant size configuration data (1, 2 or 4 bytes) */
3147   {
3148     int value = (byte_mask == CONF_MASK_1_BYTE ? getFile8Bit   (file) :
3149                  byte_mask == CONF_MASK_2_BYTE ? getFile16BitBE(file) :
3150                  byte_mask == CONF_MASK_4_BYTE ? getFile32BitBE(file) : 0);
3151
3152     for (i = 0; conf[i].data_type != -1; i++)
3153     {
3154       if (conf[i].element == element &&
3155           conf[i].conf_type == conf_type)
3156       {
3157         int data_type = conf[i].data_type;
3158
3159         if (data_type == TYPE_ELEMENT)
3160           value = getMappedElement(value);
3161
3162         if (data_type == TYPE_BOOLEAN)
3163           *(boolean *)(conf[i].value) = value;
3164         else
3165           *(int *)    (conf[i].value) = value;
3166
3167         element_found = TRUE;
3168
3169         break;
3170       }
3171     }
3172
3173     micro_chunk_size += CONF_VALUE_NUM_BYTES(byte_mask);
3174   }
3175
3176   if (!element_found)
3177   {
3178     char *error_conf_chunk_bytes =
3179       (byte_mask == CONF_MASK_1_BYTE ? "CONF_VALUE_8_BIT" :
3180        byte_mask == CONF_MASK_2_BYTE ? "CONF_VALUE_16_BIT" :
3181        byte_mask == CONF_MASK_4_BYTE ? "CONF_VALUE_32_BIT" :"CONF_VALUE_BYTES");
3182     int error_conf_chunk_token = conf_type & CONF_MASK_TOKEN;
3183     int error_element = real_element;
3184
3185     Error(ERR_WARN, "cannot load micro chunk '%s(%d)' value for element %d ['%s']",
3186           error_conf_chunk_bytes, error_conf_chunk_token,
3187           error_element, EL_NAME(error_element));
3188   }
3189
3190   return micro_chunk_size;
3191 }
3192
3193 static int LoadLevel_INFO(File *file, int chunk_size, struct LevelInfo *level)
3194 {
3195   int real_chunk_size = 0;
3196
3197   li = *level;          /* copy level data into temporary buffer */
3198
3199   while (!checkEndOfFile(file))
3200   {
3201     real_chunk_size += LoadLevel_MicroChunk(file, chunk_config_INFO, -1, -1);
3202
3203     if (real_chunk_size >= chunk_size)
3204       break;
3205   }
3206
3207   *level = li;          /* copy temporary buffer back to level data */
3208
3209   return real_chunk_size;
3210 }
3211
3212 static int LoadLevel_CONF(File *file, int chunk_size, struct LevelInfo *level)
3213 {
3214   int real_chunk_size = 0;
3215
3216   li = *level;          /* copy level data into temporary buffer */
3217
3218   while (!checkEndOfFile(file))
3219   {
3220     int element = getMappedElement(getFile16BitBE(file));
3221
3222     real_chunk_size += 2;
3223     real_chunk_size += LoadLevel_MicroChunk(file, chunk_config_CONF,
3224                                             element, element);
3225     if (real_chunk_size >= chunk_size)
3226       break;
3227   }
3228
3229   *level = li;          /* copy temporary buffer back to level data */
3230
3231   return real_chunk_size;
3232 }
3233
3234 static int LoadLevel_ELEM(File *file, int chunk_size, struct LevelInfo *level)
3235 {
3236   int real_chunk_size = 0;
3237
3238   li = *level;          /* copy level data into temporary buffer */
3239
3240   while (!checkEndOfFile(file))
3241   {
3242     int element = getMappedElement(getFile16BitBE(file));
3243
3244     real_chunk_size += 2;
3245     real_chunk_size += LoadLevel_MicroChunk(file, chunk_config_ELEM,
3246                                             element, element);
3247     if (real_chunk_size >= chunk_size)
3248       break;
3249   }
3250
3251   *level = li;          /* copy temporary buffer back to level data */
3252
3253   return real_chunk_size;
3254 }
3255
3256 static int LoadLevel_NOTE(File *file, int chunk_size, struct LevelInfo *level)
3257 {
3258   int element = getMappedElement(getFile16BitBE(file));
3259   int envelope_nr = element - EL_ENVELOPE_1;
3260   int real_chunk_size = 2;
3261
3262   while (!checkEndOfFile(file))
3263   {
3264     real_chunk_size += LoadLevel_MicroChunk(file, chunk_config_NOTE,
3265                                             -1, element);
3266
3267     if (real_chunk_size >= chunk_size)
3268       break;
3269   }
3270
3271   level->envelope[envelope_nr] = xx_envelope;
3272
3273   return real_chunk_size;
3274 }
3275
3276 static int LoadLevel_CUSX(File *file, int chunk_size, struct LevelInfo *level)
3277 {
3278   int element = getMappedElement(getFile16BitBE(file));
3279   int real_chunk_size = 2;
3280   struct ElementInfo *ei = &element_info[element];
3281   int i;
3282
3283   xx_ei = *ei;          /* copy element data into temporary buffer */
3284
3285   xx_ei.num_change_pages = -1;
3286
3287   while (!checkEndOfFile(file))
3288   {
3289     real_chunk_size += LoadLevel_MicroChunk(file, chunk_config_CUSX_base,
3290                                             -1, element);
3291     if (xx_ei.num_change_pages != -1)
3292       break;
3293
3294     if (real_chunk_size >= chunk_size)
3295       break;
3296   }
3297
3298   *ei = xx_ei;
3299
3300   if (ei->num_change_pages == -1)
3301   {
3302     Error(ERR_WARN, "LoadLevel_CUSX(): missing 'num_change_pages' for '%s'",
3303           EL_NAME(element));
3304
3305     ei->num_change_pages = 1;
3306
3307     setElementChangePages(ei, 1);
3308     setElementChangeInfoToDefaults(ei->change);
3309
3310     return real_chunk_size;
3311   }
3312
3313   /* initialize number of change pages stored for this custom element */
3314   setElementChangePages(ei, ei->num_change_pages);
3315   for (i = 0; i < ei->num_change_pages; i++)
3316     setElementChangeInfoToDefaults(&ei->change_page[i]);
3317
3318   /* start with reading properties for the first change page */
3319   xx_current_change_page = 0;
3320
3321   while (!checkEndOfFile(file))
3322   {
3323     struct ElementChangeInfo *change = &ei->change_page[xx_current_change_page];
3324
3325     xx_change = *change;        /* copy change data into temporary buffer */
3326
3327     resetEventBits();           /* reset bits; change page might have changed */
3328
3329     real_chunk_size += LoadLevel_MicroChunk(file, chunk_config_CUSX_change,
3330                                             -1, element);
3331
3332     *change = xx_change;
3333
3334     setEventFlagsFromEventBits(change);
3335
3336     if (real_chunk_size >= chunk_size)
3337       break;
3338   }
3339
3340   return real_chunk_size;
3341 }
3342
3343 static int LoadLevel_GRPX(File *file, int chunk_size, struct LevelInfo *level)
3344 {
3345   int element = getMappedElement(getFile16BitBE(file));
3346   int real_chunk_size = 2;
3347   struct ElementInfo *ei = &element_info[element];
3348   struct ElementGroupInfo *group = ei->group;
3349
3350   xx_ei = *ei;          /* copy element data into temporary buffer */
3351   xx_group = *group;    /* copy group data into temporary buffer */
3352
3353   while (!checkEndOfFile(file))
3354   {
3355     real_chunk_size += LoadLevel_MicroChunk(file, chunk_config_GRPX,
3356                                             -1, element);
3357
3358     if (real_chunk_size >= chunk_size)
3359       break;
3360   }
3361
3362   *ei = xx_ei;
3363   *group = xx_group;
3364
3365   return real_chunk_size;
3366 }
3367
3368 #else
3369
3370 static int LoadLevel_VERS(FILE *file, int chunk_size, struct LevelInfo *level)
3371 {
3372   level->file_version = getFileVersion(file);
3373   level->game_version = getFileVersion(file);
3374
3375   return chunk_size;
3376 }
3377
3378 static int LoadLevel_DATE(FILE *file, int chunk_size, struct LevelInfo *level)
3379 {
3380   level->creation_date.year  = getFile16BitBE(file);
3381   level->creation_date.month = getFile8Bit(file);
3382   level->creation_date.day   = getFile8Bit(file);
3383
3384   level->creation_date.src   = DATE_SRC_LEVELFILE;
3385
3386   return chunk_size;
3387 }
3388
3389 static int LoadLevel_HEAD(FILE *file, int chunk_size, struct LevelInfo *level)
3390 {
3391   int initial_player_stepsize;
3392   int initial_player_gravity;
3393   int i, x, y;
3394
3395   level->fieldx = getFile8Bit(file);
3396   level->fieldy = getFile8Bit(file);
3397
3398   level->time           = getFile16BitBE(file);
3399   level->gems_needed    = getFile16BitBE(file);
3400
3401   for (i = 0; i < MAX_LEVEL_NAME_LEN; i++)
3402     level->name[i] = getFile8Bit(file);
3403   level->name[MAX_LEVEL_NAME_LEN] = 0;
3404
3405   for (i = 0; i < LEVEL_SCORE_ELEMENTS; i++)
3406     level->score[i] = getFile8Bit(file);
3407
3408   level->num_yamyam_contents = STD_ELEMENT_CONTENTS;
3409   for (i = 0; i < STD_ELEMENT_CONTENTS; i++)
3410     for (y = 0; y < 3; y++)
3411       for (x = 0; x < 3; x++)
3412         level->yamyam_content[i].e[x][y] = getMappedElement(getFile8Bit(file));
3413
3414   level->amoeba_speed           = getFile8Bit(file);
3415   level->time_magic_wall        = getFile8Bit(file);
3416   level->time_wheel             = getFile8Bit(file);
3417   level->amoeba_content         = getMappedElement(getFile8Bit(file));
3418
3419   initial_player_stepsize       = (getFile8Bit(file) == 1 ? STEPSIZE_FAST :
3420                                    STEPSIZE_NORMAL);
3421
3422   for (i = 0; i < MAX_PLAYERS; i++)
3423     level->initial_player_stepsize[i] = initial_player_stepsize;
3424
3425   initial_player_gravity        = (getFile8Bit(file) == 1 ? TRUE : FALSE);
3426
3427   for (i = 0; i < MAX_PLAYERS; i++)
3428     level->initial_player_gravity[i] = initial_player_gravity;
3429
3430   level->encoding_16bit_field   = (getFile8Bit(file) == 1 ? TRUE : FALSE);
3431   level->em_slippery_gems       = (getFile8Bit(file) == 1 ? TRUE : FALSE);
3432
3433   level->use_custom_template    = (getFile8Bit(file) == 1 ? TRUE : FALSE);
3434
3435   level->block_last_field       = (getFile8Bit(file) == 1 ? TRUE : FALSE);
3436   level->sp_block_last_field    = (getFile8Bit(file) == 1 ? TRUE : FALSE);
3437   level->can_move_into_acid_bits = getFile32BitBE(file);
3438   level->dont_collide_with_bits = getFile8Bit(file);
3439
3440   level->use_spring_bug         = (getFile8Bit(file) == 1 ? TRUE : FALSE);
3441   level->use_step_counter       = (getFile8Bit(file) == 1 ? TRUE : FALSE);
3442
3443   level->instant_relocation     = (getFile8Bit(file) == 1 ? TRUE : FALSE);
3444   level->can_pass_to_walkable   = (getFile8Bit(file) == 1 ? TRUE : FALSE);
3445   level->grow_into_diggable     = (getFile8Bit(file) == 1 ? TRUE : FALSE);
3446
3447   level->game_engine_type       = getFile8Bit(file);
3448
3449   ReadUnusedBytesFromFile(file, LEVEL_CHUNK_HEAD_UNUSED);
3450
3451   return chunk_size;
3452 }
3453
3454 static int LoadLevel_NAME(FILE *file, int chunk_size, struct LevelInfo *level)
3455 {
3456   int i;
3457
3458   for (i = 0; i < MAX_LEVEL_NAME_LEN; i++)
3459     level->name[i] = getFile8Bit(file);
3460   level->name[MAX_LEVEL_NAME_LEN] = 0;
3461
3462   return chunk_size;
3463 }
3464
3465 static int LoadLevel_AUTH(FILE *file, int chunk_size, struct LevelInfo *level)
3466 {
3467   int i;
3468
3469   for (i = 0; i < MAX_LEVEL_AUTHOR_LEN; i++)
3470     level->author[i] = getFile8Bit(file);
3471   level->author[MAX_LEVEL_AUTHOR_LEN] = 0;
3472
3473   return chunk_size;
3474 }
3475
3476 static int LoadLevel_BODY(FILE *file, int chunk_size, struct LevelInfo *level)
3477 {
3478   int x, y;
3479   int chunk_size_expected = level->fieldx * level->fieldy;
3480
3481   /* Note: "chunk_size" was wrong before version 2.0 when elements are
3482      stored with 16-bit encoding (and should be twice as big then).
3483      Even worse, playfield data was stored 16-bit when only yamyam content
3484      contained 16-bit elements and vice versa. */
3485
3486   if (level->encoding_16bit_field && level->file_version >= FILE_VERSION_2_0)
3487     chunk_size_expected *= 2;
3488
3489   if (chunk_size_expected != chunk_size)
3490   {
3491     ReadUnusedBytesFromFile(file, chunk_size);
3492     return chunk_size_expected;
3493   }
3494
3495   for (y = 0; y < level->fieldy; y++)
3496     for (x = 0; x < level->fieldx; x++)
3497       level->field[x][y] =
3498         getMappedElement(level->encoding_16bit_field ? getFile16BitBE(file) :
3499                          getFile8Bit(file));
3500   return chunk_size;
3501 }
3502
3503 static int LoadLevel_CONT(FILE *file, int chunk_size, struct LevelInfo *level)
3504 {
3505   int i, x, y;
3506   int header_size = 4;
3507   int content_size = MAX_ELEMENT_CONTENTS * 3 * 3;
3508   int chunk_size_expected = header_size + content_size;
3509
3510   /* Note: "chunk_size" was wrong before version 2.0 when elements are
3511      stored with 16-bit encoding (and should be twice as big then).
3512      Even worse, playfield data was stored 16-bit when only yamyam content
3513      contained 16-bit elements and vice versa. */
3514
3515   if (level->encoding_16bit_field && level->file_version >= FILE_VERSION_2_0)
3516     chunk_size_expected += content_size;
3517
3518   if (chunk_size_expected != chunk_size)
3519   {
3520     ReadUnusedBytesFromFile(file, chunk_size);
3521     return chunk_size_expected;
3522   }
3523
3524   getFile8Bit(file);
3525   level->num_yamyam_contents = getFile8Bit(file);
3526   getFile8Bit(file);
3527   getFile8Bit(file);
3528
3529   /* correct invalid number of content fields -- should never happen */
3530   if (level->num_yamyam_contents < 1 ||
3531       level->num_yamyam_contents > MAX_ELEMENT_CONTENTS)
3532     level->num_yamyam_contents = STD_ELEMENT_CONTENTS;
3533
3534   for (i = 0; i < MAX_ELEMENT_CONTENTS; i++)
3535     for (y = 0; y < 3; y++)
3536       for (x = 0; x < 3; x++)
3537         level->yamyam_content[i].e[x][y] =
3538           getMappedElement(level->encoding_16bit_field ?
3539                            getFile16BitBE(file) : getFile8Bit(file));
3540   return chunk_size;
3541 }
3542
3543 static int LoadLevel_CNT2(FILE *file, int chunk_size, struct LevelInfo *level)
3544 {
3545   int i, x, y;
3546   int element;
3547   int num_contents;
3548 #if 0
3549   int content_xsize, content_ysize;
3550 #endif
3551   int content_array[MAX_ELEMENT_CONTENTS][3][3];
3552
3553   element = getMappedElement(getFile16BitBE(file));
3554   num_contents = getFile8Bit(file);
3555 #if 1
3556   getFile8Bit(file);    /* content x size (unused) */
3557   getFile8Bit(file);    /* content y size (unused) */
3558 #else
3559   content_xsize = getFile8Bit(file);
3560   content_ysize = getFile8Bit(file);
3561 #endif
3562
3563   ReadUnusedBytesFromFile(file, LEVEL_CHUNK_CNT2_UNUSED);
3564
3565   for (i = 0; i < MAX_ELEMENT_CONTENTS; i++)
3566     for (y = 0; y < 3; y++)
3567       for (x = 0; x < 3; x++)
3568         content_array[i][x][y] = getMappedElement(getFile16BitBE(file));
3569
3570   /* correct invalid number of content fields -- should never happen */
3571   if (num_contents < 1 || num_contents > MAX_ELEMENT_CONTENTS)
3572     num_contents = STD_ELEMENT_CONTENTS;
3573
3574   if (element == EL_YAMYAM)
3575   {
3576     level->num_yamyam_contents = num_contents;
3577
3578     for (i = 0; i < num_contents; i++)
3579       for (y = 0; y < 3; y++)
3580         for (x = 0; x < 3; x++)
3581           level->yamyam_content[i].e[x][y] = content_array[i][x][y];
3582   }
3583   else if (element == EL_BD_AMOEBA)
3584   {
3585     level->amoeba_content = content_array[0][0][0];
3586   }
3587   else
3588   {
3589     Error(ERR_WARN, "cannot load content for element '%d'", element);
3590   }
3591
3592   return chunk_size;
3593 }
3594
3595 static int LoadLevel_CNT3(FILE *file, int chunk_size, struct LevelInfo *level)
3596 {
3597   int i;
3598   int element;
3599   int envelope_nr;
3600   int envelope_len;
3601   int chunk_size_expected;
3602
3603   element = getMappedElement(getFile16BitBE(file));
3604   if (!IS_ENVELOPE(element))
3605     element = EL_ENVELOPE_1;
3606
3607   envelope_nr = element - EL_ENVELOPE_1;
3608
3609   envelope_len = getFile16BitBE(file);
3610
3611   level->envelope[envelope_nr].xsize = getFile8Bit(file);
3612   level->envelope[envelope_nr].ysize = getFile8Bit(file);
3613
3614   ReadUnusedBytesFromFile(file, LEVEL_CHUNK_CNT3_UNUSED);
3615
3616   chunk_size_expected = LEVEL_CHUNK_CNT3_SIZE(envelope_len);
3617   if (chunk_size_expected != chunk_size)
3618   {
3619     ReadUnusedBytesFromFile(file, chunk_size - LEVEL_CHUNK_CNT3_HEADER);
3620     return chunk_size_expected;
3621   }
3622
3623   for (i = 0; i < envelope_len; i++)
3624     level->envelope[envelope_nr].text[i] = getFile8Bit(file);
3625
3626   return chunk_size;
3627 }
3628
3629 static int LoadLevel_CUS1(FILE *file, int chunk_size, struct LevelInfo *level)
3630 {
3631   int num_changed_custom_elements = getFile16BitBE(file);
3632   int chunk_size_expected = 2 + num_changed_custom_elements * 6;
3633   int i;
3634
3635   if (chunk_size_expected != chunk_size)
3636   {
3637     ReadUnusedBytesFromFile(file, chunk_size - 2);
3638     return chunk_size_expected;
3639   }
3640
3641   for (i = 0; i < num_changed_custom_elements; i++)
3642   {
3643     int element = getMappedElement(getFile16BitBE(file));
3644     int properties = getFile32BitBE(file);
3645
3646     if (IS_CUSTOM_ELEMENT(element))
3647       element_info[element].properties[EP_BITFIELD_BASE_NR] = properties;
3648     else
3649       Error(ERR_WARN, "invalid custom element number %d", element);
3650
3651     /* older game versions that wrote level files with CUS1 chunks used
3652        different default push delay values (not yet stored in level file) */
3653     element_info[element].push_delay_fixed = 2;
3654     element_info[element].push_delay_random = 8;
3655   }
3656
3657   return chunk_size;
3658 }
3659
3660 static int LoadLevel_CUS2(FILE *file, int chunk_size, struct LevelInfo *level)
3661 {
3662   int num_changed_custom_elements = getFile16BitBE(file);
3663   int chunk_size_expected = 2 + num_changed_custom_elements * 4;
3664   int i;
3665
3666   if (chunk_size_expected != chunk_size)
3667   {
3668     ReadUnusedBytesFromFile(file, chunk_size - 2);
3669     return chunk_size_expected;
3670   }
3671
3672   for (i = 0; i < num_changed_custom_elements; i++)
3673   {
3674     int element = getMappedElement(getFile16BitBE(file));
3675     int custom_target_element = getMappedElement(getFile16BitBE(file));
3676
3677     if (IS_CUSTOM_ELEMENT(element))
3678       element_info[element].change->target_element = custom_target_element;
3679     else
3680       Error(ERR_WARN, "invalid custom element number %d", element);
3681   }
3682
3683   return chunk_size;
3684 }
3685
3686 static int LoadLevel_CUS3(FILE *file, int chunk_size, struct LevelInfo *level)
3687 {
3688   int num_changed_custom_elements = getFile16BitBE(file);
3689   int chunk_size_expected = LEVEL_CHUNK_CUS3_SIZE(num_changed_custom_elements);
3690   int i, j, x, y;
3691
3692   if (chunk_size_expected != chunk_size)
3693   {
3694     ReadUnusedBytesFromFile(file, chunk_size - 2);
3695     return chunk_size_expected;
3696   }
3697
3698   for (i = 0; i < num_changed_custom_elements; i++)
3699   {
3700     int element = getMappedElement(getFile16BitBE(file));
3701     struct ElementInfo *ei = &element_info[element];
3702     unsigned int event_bits;
3703
3704     if (!IS_CUSTOM_ELEMENT(element))
3705     {
3706       Error(ERR_WARN, "invalid custom element number %d", element);
3707
3708       element = EL_INTERNAL_DUMMY;
3709     }
3710
3711     for (j = 0; j < MAX_ELEMENT_NAME_LEN; j++)
3712       ei->description[j] = getFile8Bit(file);
3713     ei->description[MAX_ELEMENT_NAME_LEN] = 0;
3714
3715     ei->properties[EP_BITFIELD_BASE_NR] = getFile32BitBE(file);
3716
3717     /* some free bytes for future properties and padding */
3718     ReadUnusedBytesFromFile(file, 7);
3719
3720     ei->use_gfx_element = getFile8Bit(file);
3721     ei->gfx_element_initial = getMappedElement(getFile16BitBE(file));
3722
3723     ei->collect_score_initial = getFile8Bit(file);
3724     ei->collect_count_initial = getFile8Bit(file);
3725
3726     ei->push_delay_fixed = getFile16BitBE(file);
3727     ei->push_delay_random = getFile16BitBE(file);
3728     ei->move_delay_fixed = getFile16BitBE(file);
3729     ei->move_delay_random = getFile16BitBE(file);
3730
3731     ei->move_pattern = getFile16BitBE(file);
3732     ei->move_direction_initial = getFile8Bit(file);
3733     ei->move_stepsize = getFile8Bit(file);
3734
3735     for (y = 0; y < 3; y++)
3736       for (x = 0; x < 3; x++)
3737         ei->content.e[x][y] = getMappedElement(getFile16BitBE(file));
3738
3739     event_bits = getFile32BitBE(file);
3740     for (j = 0; j < NUM_CHANGE_EVENTS; j++)
3741       if (event_bits & (1 << j))
3742         ei->change->has_event[j] = TRUE;
3743
3744     ei->change->target_element = getMappedElement(getFile16BitBE(file));
3745
3746     ei->change->delay_fixed = getFile16BitBE(file);
3747     ei->change->delay_random = getFile16BitBE(file);
3748     ei->change->delay_frames = getFile16BitBE(file);
3749
3750     ei->change->initial_trigger_element= getMappedElement(getFile16BitBE(file));
3751
3752     ei->change->explode = getFile8Bit(file);
3753     ei->change->use_target_content = getFile8Bit(file);
3754     ei->change->only_if_complete = getFile8Bit(file);
3755     ei->change->use_random_replace = getFile8Bit(file);
3756
3757     ei->change->random_percentage = getFile8Bit(file);
3758     ei->change->replace_when = getFile8Bit(file);
3759
3760     for (y = 0; y < 3; y++)
3761       for (x = 0; x < 3; x++)
3762         ei->change->target_content.e[x][y] =
3763           getMappedElement(getFile16BitBE(file));
3764
3765     ei->slippery_type = getFile8Bit(file);
3766
3767     /* some free bytes for future properties and padding */
3768     ReadUnusedBytesFromFile(file, LEVEL_CPART_CUS3_UNUSED);
3769
3770     /* mark that this custom element has been modified */
3771     ei->modified_settings = TRUE;
3772   }
3773
3774   return chunk_size;
3775 }
3776
3777 static int LoadLevel_CUS4(FILE *file, int chunk_size, struct LevelInfo *level)
3778 {
3779   struct ElementInfo *ei;
3780   int chunk_size_expected;
3781   int element;
3782   int i, j, x, y;
3783
3784   /* ---------- custom element base property values (96 bytes) ------------- */
3785
3786   element = getMappedElement(getFile16BitBE(file));
3787
3788   if (!IS_CUSTOM_ELEMENT(element))
3789   {
3790     Error(ERR_WARN, "invalid custom element number %d", element);
3791
3792     ReadUnusedBytesFromFile(file, chunk_size - 2);
3793     return chunk_size;
3794   }
3795
3796   ei = &element_info[element];
3797
3798   for (i = 0; i < MAX_ELEMENT_NAME_LEN; i++)
3799     ei->description[i] = getFile8Bit(file);
3800   ei->description[MAX_ELEMENT_NAME_LEN] = 0;
3801
3802   ei->properties[EP_BITFIELD_BASE_NR] = getFile32BitBE(file);
3803
3804   ReadUnusedBytesFromFile(file, 4);     /* reserved for more base properties */
3805
3806   ei->num_change_pages = getFile8Bit(file);
3807
3808   chunk_size_expected = LEVEL_CHUNK_CUS4_SIZE(ei->num_change_pages);
3809   if (chunk_size_expected != chunk_size)
3810   {
3811     ReadUnusedBytesFromFile(file, chunk_size - 43);
3812     return chunk_size_expected;
3813   }
3814
3815   ei->ce_value_fixed_initial = getFile16BitBE(file);
3816   ei->ce_value_random_initial = getFile16BitBE(file);
3817   ei->use_last_ce_value = getFile8Bit(file);
3818
3819   ei->use_gfx_element = getFile8Bit(file);
3820   ei->gfx_element_initial = getMappedElement(getFile16BitBE(file));
3821
3822   ei->collect_score_initial = getFile8Bit(file);
3823   ei->collect_count_initial = getFile8Bit(file);
3824
3825   ei->drop_delay_fixed = getFile8Bit(file);
3826   ei->push_delay_fixed = getFile8Bit(file);
3827   ei->drop_delay_random = getFile8Bit(file);
3828   ei->push_delay_random = getFile8Bit(file);
3829   ei->move_delay_fixed = getFile16BitBE(file);
3830   ei->move_delay_random = getFile16BitBE(file);
3831
3832   /* bits 0 - 15 of "move_pattern" ... */
3833   ei->move_pattern = getFile16BitBE(file);
3834   ei->move_direction_initial = getFile8Bit(file);
3835   ei->move_stepsize = getFile8Bit(file);
3836
3837   ei->slippery_type = getFile8Bit(file);
3838
3839   for (y = 0; y < 3; y++)
3840     for (x = 0; x < 3; x++)
3841       ei->content.e[x][y] = getMappedElement(getFile16BitBE(file));
3842
3843   ei->move_enter_element = getMappedElement(getFile16BitBE(file));
3844   ei->move_leave_element = getMappedElement(getFile16BitBE(file));
3845   ei->move_leave_type = getFile8Bit(file);
3846
3847   /* ... bits 16 - 31 of "move_pattern" (not nice, but downward compatible) */
3848   ei->move_pattern |= (getFile16BitBE(file) << 16);
3849
3850   ei->access_direction = getFile8Bit(file);
3851
3852   ei->explosion_delay = getFile8Bit(file);
3853   ei->ignition_delay = getFile8Bit(file);
3854   ei->explosion_type = getFile8Bit(file);
3855
3856   /* some free bytes for future custom property values and padding */
3857   ReadUnusedBytesFromFile(file, 1);
3858
3859   /* ---------- change page property values (48 bytes) --------------------- */
3860
3861   setElementChangePages(ei, ei->num_change_pages);
3862
3863   for (i = 0; i < ei->num_change_pages; i++)
3864   {
3865     struct ElementChangeInfo *change = &ei->change_page[i];
3866     unsigned int event_bits;
3867
3868     /* always start with reliable default values */
3869     setElementChangeInfoToDefaults(change);
3870
3871     /* bits 0 - 31 of "has_event[]" ... */
3872     event_bits = getFile32BitBE(file);
3873     for (j = 0; j < MIN(NUM_CHANGE_EVENTS, 32); j++)
3874       if (event_bits & (1 << j))
3875         change->has_event[j] = TRUE;
3876
3877     change->target_element = getMappedElement(getFile16BitBE(file));
3878
3879     change->delay_fixed = getFile16BitBE(file);
3880     change->delay_random = getFile16BitBE(file);
3881     change->delay_frames = getFile16BitBE(file);
3882
3883     change->initial_trigger_element = getMappedElement(getFile16BitBE(file));
3884
3885     change->explode = getFile8Bit(file);
3886     change->use_target_content = getFile8Bit(file);
3887     change->only_if_complete = getFile8Bit(file);
3888     change->use_random_replace = getFile8Bit(file);
3889
3890     change->random_percentage = getFile8Bit(file);
3891     change->replace_when = getFile8Bit(file);
3892
3893     for (y = 0; y < 3; y++)
3894       for (x = 0; x < 3; x++)
3895         change->target_content.e[x][y]= getMappedElement(getFile16BitBE(file));
3896
3897     change->can_change = getFile8Bit(file);
3898
3899     change->trigger_side = getFile8Bit(file);
3900
3901     change->trigger_player = getFile8Bit(file);
3902     change->trigger_page = getFile8Bit(file);
3903
3904     change->trigger_page = (change->trigger_page == CH_PAGE_ANY_FILE ?
3905                             CH_PAGE_ANY : (1 << change->trigger_page));
3906
3907     change->has_action = getFile8Bit(file);
3908     change->action_type = getFile8Bit(file);
3909     change->action_mode = getFile8Bit(file);
3910     change->action_arg = getFile16BitBE(file);
3911
3912     /* ... bits 32 - 39 of "has_event[]" (not nice, but downward compatible) */
3913     event_bits = getFile8Bit(file);
3914     for (j = 32; j < NUM_CHANGE_EVENTS; j++)
3915       if (event_bits & (1 << (j - 32)))
3916         change->has_event[j] = TRUE;
3917   }
3918
3919   /* mark this custom element as modified */
3920   ei->modified_settings = TRUE;
3921
3922   return chunk_size;
3923 }
3924
3925 static int LoadLevel_GRP1(FILE *file, int chunk_size, struct LevelInfo *level)
3926 {
3927   struct ElementInfo *ei;
3928   struct ElementGroupInfo *group;
3929   int element;
3930   int i;
3931
3932   element = getMappedElement(getFile16BitBE(file));
3933
3934   if (!IS_GROUP_ELEMENT(element))
3935   {
3936     Error(ERR_WARN, "invalid group element number %d", element);
3937
3938     ReadUnusedBytesFromFile(file, chunk_size - 2);
3939     return chunk_size;
3940   }
3941
3942   ei = &element_info[element];
3943
3944   for (i = 0; i < MAX_ELEMENT_NAME_LEN; i++)
3945     ei->description[i] = getFile8Bit(file);
3946   ei->description[MAX_ELEMENT_NAME_LEN] = 0;
3947
3948   group = element_info[element].group;
3949
3950   group->num_elements = getFile8Bit(file);
3951
3952   ei->use_gfx_element = getFile8Bit(file);
3953   ei->gfx_element_initial = getMappedElement(getFile16BitBE(file));
3954
3955   group->choice_mode = getFile8Bit(file);
3956
3957   /* some free bytes for future values and padding */
3958   ReadUnusedBytesFromFile(file, 3);
3959
3960   for (i = 0; i < MAX_ELEMENTS_IN_GROUP; i++)
3961     group->element[i] = getMappedElement(getFile16BitBE(file));
3962
3963   /* mark this group element as modified */
3964   element_info[element].modified_settings = TRUE;
3965
3966   return chunk_size;
3967 }
3968
3969 static int LoadLevel_MicroChunk(FILE *file, struct LevelFileConfigInfo *conf,
3970                                 int element, int real_element)
3971 {
3972   int micro_chunk_size = 0;
3973   int conf_type = getFile8Bit(file);
3974   int byte_mask = conf_type & CONF_MASK_BYTES;
3975   boolean element_found = FALSE;
3976   int i;
3977
3978   micro_chunk_size += 1;
3979
3980   if (byte_mask == CONF_MASK_MULTI_BYTES)
3981   {
3982     int num_bytes = getFile16BitBE(file);
3983     byte *buffer = checked_malloc(num_bytes);
3984
3985     ReadBytesFromFile(file, buffer, num_bytes);
3986
3987     for (i = 0; conf[i].data_type != -1; i++)
3988     {
3989       if (conf[i].element == element &&
3990           conf[i].conf_type == conf_type)
3991       {
3992         int data_type = conf[i].data_type;
3993         int num_entities = num_bytes / CONF_ENTITY_NUM_BYTES(data_type);
3994         int max_num_entities = conf[i].max_num_entities;
3995
3996         if (num_entities > max_num_entities)
3997         {
3998           Error(ERR_WARN,
3999                 "truncating number of entities for element %d from %d to %d",
4000                 element, num_entities, max_num_entities);
4001
4002           num_entities = max_num_entities;
4003         }
4004
4005         if (num_entities == 0 && (data_type == TYPE_ELEMENT_LIST ||
4006                                   data_type == TYPE_CONTENT_LIST))
4007         {
4008           /* for element and content lists, zero entities are not allowed */
4009           Error(ERR_WARN, "found empty list of entities for element %d",
4010                 element);
4011
4012           /* do not set "num_entities" here to prevent reading behind buffer */
4013
4014           *(int *)(conf[i].num_entities) = 1;   /* at least one is required */
4015         }
4016         else
4017         {
4018           *(int *)(conf[i].num_entities) = num_entities;
4019         }
4020
4021         element_found = TRUE;
4022
4023         if (data_type == TYPE_STRING)
4024         {
4025           char *string = (char *)(conf[i].value);
4026           int j;
4027
4028           for (j = 0; j < max_num_entities; j++)
4029             string[j] = (j < num_entities ? buffer[j] : '\0');
4030         }
4031         else if (data_type == TYPE_ELEMENT_LIST)
4032         {
4033           int *element_array = (int *)(conf[i].value);
4034           int j;
4035
4036           for (j = 0; j < num_entities; j++)
4037             element_array[j] =
4038               getMappedElement(CONF_ELEMENTS_ELEMENT(buffer, j));
4039         }
4040         else if (data_type == TYPE_CONTENT_LIST)
4041         {
4042           struct Content *content= (struct Content *)(conf[i].value);
4043           int c, x, y;
4044
4045           for (c = 0; c < num_entities; c++)
4046             for (y = 0; y < 3; y++)
4047               for (x = 0; x < 3; x++)
4048                 content[c].e[x][y] =
4049                   getMappedElement(CONF_CONTENTS_ELEMENT(buffer, c, x, y));
4050         }
4051         else
4052           element_found = FALSE;
4053
4054         break;
4055       }
4056     }
4057
4058     checked_free(buffer);
4059
4060     micro_chunk_size += 2 + num_bytes;
4061   }
4062   else          /* constant size configuration data (1, 2 or 4 bytes) */
4063   {
4064     int value = (byte_mask == CONF_MASK_1_BYTE ? getFile8Bit   (file) :
4065                  byte_mask == CONF_MASK_2_BYTE ? getFile16BitBE(file) :
4066                  byte_mask == CONF_MASK_4_BYTE ? getFile32BitBE(file) : 0);
4067
4068     for (i = 0; conf[i].data_type != -1; i++)
4069     {
4070       if (conf[i].element == element &&
4071           conf[i].conf_type == conf_type)
4072       {
4073         int data_type = conf[i].data_type;
4074
4075         if (data_type == TYPE_ELEMENT)
4076           value = getMappedElement(value);
4077
4078         if (data_type == TYPE_BOOLEAN)
4079           *(boolean *)(conf[i].value) = value;
4080         else
4081           *(int *)    (conf[i].value) = value;
4082
4083         element_found = TRUE;
4084
4085         break;
4086       }
4087     }
4088
4089     micro_chunk_size += CONF_VALUE_NUM_BYTES(byte_mask);
4090   }
4091
4092   if (!element_found)
4093   {
4094     char *error_conf_chunk_bytes =
4095       (byte_mask == CONF_MASK_1_BYTE ? "CONF_VALUE_8_BIT" :
4096        byte_mask == CONF_MASK_2_BYTE ? "CONF_VALUE_16_BIT" :
4097        byte_mask == CONF_MASK_4_BYTE ? "CONF_VALUE_32_BIT" :"CONF_VALUE_BYTES");
4098     int error_conf_chunk_token = conf_type & CONF_MASK_TOKEN;
4099     int error_element = real_element;
4100
4101     Error(ERR_WARN, "cannot load micro chunk '%s(%d)' value for element %d ['%s']",
4102           error_conf_chunk_bytes, error_conf_chunk_token,
4103           error_element, EL_NAME(error_element));
4104   }
4105
4106   return micro_chunk_size;
4107 }
4108
4109 static int LoadLevel_INFO(FILE *file, int chunk_size, struct LevelInfo *level)
4110 {
4111   int real_chunk_size = 0;
4112
4113   li = *level;          /* copy level data into temporary buffer */
4114
4115   while (!feof(file))
4116   {
4117     real_chunk_size += LoadLevel_MicroChunk(file, chunk_config_INFO, -1, -1);
4118
4119     if (real_chunk_size >= chunk_size)
4120       break;
4121   }
4122
4123   *level = li;          /* copy temporary buffer back to level data */
4124
4125   return real_chunk_size;
4126 }
4127
4128 static int LoadLevel_CONF(FILE *file, int chunk_size, struct LevelInfo *level)
4129 {
4130   int real_chunk_size = 0;
4131
4132   li = *level;          /* copy level data into temporary buffer */
4133
4134   while (!feof(file))
4135   {
4136     int element = getMappedElement(getFile16BitBE(file));
4137
4138     real_chunk_size += 2;
4139     real_chunk_size += LoadLevel_MicroChunk(file, chunk_config_CONF,
4140                                             element, element);
4141     if (real_chunk_size >= chunk_size)
4142       break;
4143   }
4144
4145   *level = li;          /* copy temporary buffer back to level data */
4146
4147   return real_chunk_size;
4148 }
4149
4150 static int LoadLevel_ELEM(FILE *file, int chunk_size, struct LevelInfo *level)
4151 {
4152   int real_chunk_size = 0;
4153
4154   li = *level;          /* copy level data into temporary buffer */
4155
4156   while (!feof(file))
4157   {
4158     int element = getMappedElement(getFile16BitBE(file));
4159
4160     real_chunk_size += 2;
4161     real_chunk_size += LoadLevel_MicroChunk(file, chunk_config_ELEM,
4162                                             element, element);
4163     if (real_chunk_size >= chunk_size)
4164       break;
4165   }
4166
4167   *level = li;          /* copy temporary buffer back to level data */
4168
4169   return real_chunk_size;
4170 }
4171
4172 static int LoadLevel_NOTE(FILE *file, int chunk_size, struct LevelInfo *level)
4173 {
4174   int element = getMappedElement(getFile16BitBE(file));
4175   int envelope_nr = element - EL_ENVELOPE_1;
4176   int real_chunk_size = 2;
4177
4178   while (!feof(file))
4179   {
4180     real_chunk_size += LoadLevel_MicroChunk(file, chunk_config_NOTE,
4181                                             -1, element);
4182
4183     if (real_chunk_size >= chunk_size)
4184       break;
4185   }
4186
4187   level->envelope[envelope_nr] = xx_envelope;
4188
4189   return real_chunk_size;
4190 }
4191
4192 static int LoadLevel_CUSX(FILE *file, int chunk_size, struct LevelInfo *level)
4193 {
4194   int element = getMappedElement(getFile16BitBE(file));
4195   int real_chunk_size = 2;
4196   struct ElementInfo *ei = &element_info[element];
4197   int i;
4198
4199   xx_ei = *ei;          /* copy element data into temporary buffer */
4200
4201   xx_ei.num_change_pages = -1;
4202
4203   while (!feof(file))
4204   {
4205     real_chunk_size += LoadLevel_MicroChunk(file, chunk_config_CUSX_base,
4206                                             -1, element);
4207     if (xx_ei.num_change_pages != -1)
4208       break;
4209
4210     if (real_chunk_size >= chunk_size)
4211       break;
4212   }
4213
4214   *ei = xx_ei;
4215
4216   if (ei->num_change_pages == -1)
4217   {
4218     Error(ERR_WARN, "LoadLevel_CUSX(): missing 'num_change_pages' for '%s'",
4219           EL_NAME(element));
4220
4221     ei->num_change_pages = 1;
4222
4223     setElementChangePages(ei, 1);
4224     setElementChangeInfoToDefaults(ei->change);
4225
4226     return real_chunk_size;
4227   }
4228
4229   /* initialize number of change pages stored for this custom element */
4230   setElementChangePages(ei, ei->num_change_pages);
4231   for (i = 0; i < ei->num_change_pages; i++)
4232     setElementChangeInfoToDefaults(&ei->change_page[i]);
4233
4234   /* start with reading properties for the first change page */
4235   xx_current_change_page = 0;
4236
4237   while (!feof(file))
4238   {
4239     struct ElementChangeInfo *change = &ei->change_page[xx_current_change_page];
4240
4241     xx_change = *change;        /* copy change data into temporary buffer */
4242
4243     resetEventBits();           /* reset bits; change page might have changed */
4244
4245     real_chunk_size += LoadLevel_MicroChunk(file, chunk_config_CUSX_change,
4246                                             -1, element);
4247
4248     *change = xx_change;
4249
4250     setEventFlagsFromEventBits(change);
4251
4252     if (real_chunk_size >= chunk_size)
4253       break;
4254   }
4255
4256   return real_chunk_size;
4257 }
4258
4259 static int LoadLevel_GRPX(FILE *file, int chunk_size, struct LevelInfo *level)
4260 {
4261   int element = getMappedElement(getFile16BitBE(file));
4262   int real_chunk_size = 2;
4263   struct ElementInfo *ei = &element_info[element];
4264   struct ElementGroupInfo *group = ei->group;
4265
4266   xx_ei = *ei;          /* copy element data into temporary buffer */
4267   xx_group = *group;    /* copy group data into temporary buffer */
4268
4269   while (!feof(file))
4270   {
4271     real_chunk_size += LoadLevel_MicroChunk(file, chunk_config_GRPX,
4272                                             -1, element);
4273
4274     if (real_chunk_size >= chunk_size)
4275       break;
4276   }
4277
4278   *ei = xx_ei;
4279   *group = xx_group;
4280
4281   return real_chunk_size;
4282 }
4283
4284 #endif
4285
4286 #if 1
4287
4288 static void LoadLevelFromFileInfo_RND(struct LevelInfo *level,
4289                                       struct LevelFileInfo *level_file_info,
4290                                       boolean level_info_only)
4291 {
4292   char *filename = level_file_info->filename;
4293   char cookie[MAX_LINE_LEN];
4294   char chunk_name[CHUNK_ID_LEN + 1];
4295   int chunk_size;
4296   File *file;
4297
4298   if (!(file = openFile(filename, MODE_READ)))
4299   {
4300     level->no_valid_file = TRUE;
4301
4302 #if 1
4303     if (!level_info_only)
4304       Error(ERR_WARN, "cannot read level '%s' -- using empty level", filename);
4305 #else
4306     if (level != &level_template)
4307       Error(ERR_WARN, "cannot read level '%s' -- using empty level", filename);
4308 #endif
4309
4310     return;
4311   }
4312
4313   getFileChunkBE(file, chunk_name, NULL);
4314   if (strEqual(chunk_name, "RND1"))
4315   {
4316     getFile32BitBE(file);               /* not used */
4317
4318     getFileChunkBE(file, chunk_name, NULL);
4319     if (!strEqual(chunk_name, "CAVE"))
4320     {
4321       level->no_valid_file = TRUE;
4322
4323       Error(ERR_WARN, "unknown format of level file '%s'", filename);
4324
4325       closeFile(file);
4326
4327       return;
4328     }
4329   }
4330   else  /* check for pre-2.0 file format with cookie string */
4331   {
4332     strcpy(cookie, chunk_name);
4333     if (getStringFromFile(file, &cookie[4], MAX_LINE_LEN - 4) == NULL)
4334       cookie[4] = '\0';
4335     if (strlen(cookie) > 0 && cookie[strlen(cookie) - 1] == '\n')
4336       cookie[strlen(cookie) - 1] = '\0';
4337
4338     if (!checkCookieString(cookie, LEVEL_COOKIE_TMPL))
4339     {
4340       level->no_valid_file = TRUE;
4341
4342       Error(ERR_WARN, "unknown format of level file '%s'", filename);
4343
4344       closeFile(file);
4345
4346       return;
4347     }
4348
4349     if ((level->file_version = getFileVersionFromCookieString(cookie)) == -1)
4350     {
4351       level->no_valid_file = TRUE;
4352
4353       Error(ERR_WARN, "unsupported version of level file '%s'", filename);
4354
4355       closeFile(file);
4356
4357       return;
4358     }
4359
4360     /* pre-2.0 level files have no game version, so use file version here */
4361     level->game_version = level->file_version;
4362   }
4363
4364   if (level->file_version < FILE_VERSION_1_2)
4365   {
4366     /* level files from versions before 1.2.0 without chunk structure */
4367     LoadLevel_HEAD(file, LEVEL_CHUNK_HEAD_SIZE,         level);
4368     LoadLevel_BODY(file, level->fieldx * level->fieldy, level);
4369   }
4370   else
4371   {
4372     static struct
4373     {
4374       char *name;
4375       int size;
4376       int (*loader)(File *, int, struct LevelInfo *);
4377     }
4378     chunk_info[] =
4379     {
4380       { "VERS", LEVEL_CHUNK_VERS_SIZE,  LoadLevel_VERS },
4381       { "DATE", LEVEL_CHUNK_DATE_SIZE,  LoadLevel_DATE },
4382       { "HEAD", LEVEL_CHUNK_HEAD_SIZE,  LoadLevel_HEAD },
4383       { "NAME", LEVEL_CHUNK_NAME_SIZE,  LoadLevel_NAME },
4384       { "AUTH", LEVEL_CHUNK_AUTH_SIZE,  LoadLevel_AUTH },
4385       { "INFO", -1,                     LoadLevel_INFO },
4386       { "BODY", -1,                     LoadLevel_BODY },
4387       { "CONT", -1,                     LoadLevel_CONT },
4388       { "CNT2", LEVEL_CHUNK_CNT2_SIZE,  LoadLevel_CNT2 },
4389       { "CNT3", -1,                     LoadLevel_CNT3 },
4390       { "CUS1", -1,                     LoadLevel_CUS1 },
4391       { "CUS2", -1,                     LoadLevel_CUS2 },
4392       { "CUS3", -1,                     LoadLevel_CUS3 },
4393       { "CUS4", -1,                     LoadLevel_CUS4 },
4394       { "GRP1", -1,                     LoadLevel_GRP1 },
4395       { "CONF", -1,                     LoadLevel_CONF },
4396       { "ELEM", -1,                     LoadLevel_ELEM },
4397       { "NOTE", -1,                     LoadLevel_NOTE },
4398       { "CUSX", -1,                     LoadLevel_CUSX },
4399       { "GRPX", -1,                     LoadLevel_GRPX },
4400
4401       {  NULL,  0,                      NULL }
4402     };
4403
4404     while (getFileChunkBE(file, chunk_name, &chunk_size))
4405     {
4406       int i = 0;
4407
4408       while (chunk_info[i].name != NULL &&
4409              !strEqual(chunk_name, chunk_info[i].name))
4410         i++;
4411
4412       if (chunk_info[i].name == NULL)
4413       {
4414         Error(ERR_WARN, "unknown chunk '%s' in level file '%s'",
4415               chunk_name, filename);
4416         ReadUnusedBytesFromFile(file, chunk_size);
4417       }
4418       else if (chunk_info[i].size != -1 &&
4419                chunk_info[i].size != chunk_size)
4420       {
4421         Error(ERR_WARN, "wrong size (%d) of chunk '%s' in level file '%s'",
4422               chunk_size, chunk_name, filename);
4423         ReadUnusedBytesFromFile(file, chunk_size);
4424       }
4425       else
4426       {
4427         /* call function to load this level chunk */
4428         int chunk_size_expected =
4429           (chunk_info[i].loader)(file, chunk_size, level);
4430
4431         /* the size of some chunks cannot be checked before reading other
4432            chunks first (like "HEAD" and "BODY") that contain some header
4433            information, so check them here */
4434         if (chunk_size_expected != chunk_size)
4435         {
4436           Error(ERR_WARN, "wrong size (%d) of chunk '%s' in level file '%s'",
4437                 chunk_size, chunk_name, filename);
4438         }
4439       }
4440     }
4441   }
4442
4443   closeFile(file);
4444 }
4445
4446 #else
4447
4448 static void LoadLevelFromFileInfo_RND(struct LevelInfo *level,
4449                                       struct LevelFileInfo *level_file_info,
4450                                       boolean level_info_only)
4451 {
4452   char *filename = level_file_info->filename;
4453   char cookie[MAX_LINE_LEN];
4454   char chunk_name[CHUNK_ID_LEN + 1];
4455   int chunk_size;
4456   FILE *file;
4457
4458   if (!(file = fopen(filename, MODE_READ)))
4459   {
4460     level->no_valid_file = TRUE;
4461
4462 #if 1
4463     if (!level_info_only)
4464       Error(ERR_WARN, "cannot read level '%s' -- using empty level", filename);
4465 #else
4466     if (level != &level_template)
4467       Error(ERR_WARN, "cannot read level '%s' -- using empty level", filename);
4468 #endif
4469
4470     return;
4471   }
4472
4473   getFileChunkBE(file, chunk_name, NULL);
4474   if (strEqual(chunk_name, "RND1"))
4475   {
4476     getFile32BitBE(file);               /* not used */
4477
4478     getFileChunkBE(file, chunk_name, NULL);
4479     if (!strEqual(chunk_name, "CAVE"))
4480     {
4481       level->no_valid_file = TRUE;
4482
4483       Error(ERR_WARN, "unknown format of level file '%s'", filename);
4484       fclose(file);
4485       return;
4486     }
4487   }
4488   else  /* check for pre-2.0 file format with cookie string */
4489   {
4490     strcpy(cookie, chunk_name);
4491     if (fgets(&cookie[4], MAX_LINE_LEN - 4, file) == NULL)
4492       cookie[4] = '\0';
4493     if (strlen(cookie) > 0 && cookie[strlen(cookie) - 1] == '\n')
4494       cookie[strlen(cookie) - 1] = '\0';
4495
4496     if (!checkCookieString(cookie, LEVEL_COOKIE_TMPL))
4497     {
4498       level->no_valid_file = TRUE;
4499
4500       Error(ERR_WARN, "unknown format of level file '%s'", filename);
4501       fclose(file);
4502       return;
4503     }
4504
4505     if ((level->file_version = getFileVersionFromCookieString(cookie)) == -1)
4506     {
4507       level->no_valid_file = TRUE;
4508
4509       Error(ERR_WARN, "unsupported version of level file '%s'", filename);
4510       fclose(file);
4511       return;
4512     }
4513
4514     /* pre-2.0 level files&nb