added cave buffer offsets to level structure in EM engine
[rocksndiamonds.git] / src / game_em / convert.c
1 /* 2000-08-20T09:41:18Z
2  *
3  * identify all emerald mine caves and turn them into v6 format.
4  * fixes illegal tiles, acid, wheel, limits times, cleans flags.
5  *
6  * these tables weed out bad tiles for older caves (eg. wheel on -> wheel off)
7  * and clean up v6 caves (acid, number limits) which should(!) be
8  * inconsequential, but no doubt it will break some caves.
9  */
10
11 #include "main_em.h"
12
13
14 static unsigned char remap_v6[256] =
15 {
16   /* filter crap for v6 */
17
18   0,0,2,2,         4,4,118,118,     8,9,10,11,       12,13,14,15,
19   16,16,18,18,     20,21,22,23,     24,25,26,27,     28,28,118,28,
20   0,16,2,18,       36,37,37,37,     40,41,42,43,     44,45,128,128,
21   128,148,148,     148,45,45,45,    148,0,57,58,     59,60,61,62,63,
22
23   64,65,66,67,     68,69,69,71,     72,73,74,75,     118,75,75,75,
24   75,75,75,75,     75,153,153,153,  153,153,153,153, 153,153,153,153,
25   153,153,153,99,  100,68,68,68,    68,68,68,68,     68,118,118,118,
26   118,118,114,115, 131,118,118,119, 120,121,122,118, 118,118,118,118,
27
28   128,129,130,131, 132,133,134,135, 136,137,138,139, 140,141,142,143,
29   144,145,146,147, 148,149,150,151, 152,153,154,155, 156,157,158,159,
30   160,161,162,163, 164,165,165,118, 168,169,170,171, 172,173,174,175,
31   176,177,178,179, 180,181,182,183, 184,185,186,187, 188,189,68,191,
32
33   192,193,194,195, 196,197,198,199, 200,201,202,203, 204,205,206,207,
34   208,209,210,211, 212,213,214,215, 216,217,218,219, 220,221,222,223,
35   224,225,226,227, 228,229,230,231, 232,233,234,235, 236,237,238,239,
36   240,241,242,243, 244,245,153,153, 153,153,153,153, 153,153,153,153
37 };
38
39 static unsigned char remap_v5[256] =
40 {
41   /* filter crap for v5 */
42
43   0,0,2,2,         4,4,118,118,     8,9,10,11,       12,13,14,15,
44   16,16,18,18,     20,21,22,23,     24,25,26,27,     28,28,118,28,
45   0,16,2,18,       36,37,37,37,     147,41,42,43,    44,45,128,128,
46   128,148,148,148, 45,45,45,148,    0,57,58,59,      60,61,62,63,
47
48   64,65,66,67,     68,153,153,153,  153,153,153,153, 153,153,153,153,
49   153,153,153,153, 153,153,153,153, 153,153,153,153, 153,153,153,153,
50   153,153,153,153, 153,68,68,68,68, 68,68,68,68,118, 118,118,
51   118,118,114,115, 131,118,118,119, 120,121,122,118, 118,118,118,118,
52
53   128,129,130,131, 132,133,134,135, 136,137,138,139, 140,141,142,143,
54   144,145,146,147, 148,149,150,151, 152,153,154,155, 156,157,158,159,
55   160,153,153,153, 153,153,153,118, 168,169,170,171, 172,173,174,175,
56   176,177,178,179, 180,181,182,183, 184,185,186,187, 188,189,68,153,
57
58   153,153,153,153, 153,153,153,153, 200,201,202,203, 204,205,206,207,
59   208,209,210,211, 212,213,214,215, 216,217,218,219, 220,221,222,223,
60   224,225,226,227, 228,229,230,231, 232,233,234,235, 236,237,238,239,
61   240,241,153,153, 153,153,153,153, 153,153,153,153, 153,153,153,153
62 };
63
64 static unsigned char remap_v4[256] =
65 {
66   /* filter crap for v4 */
67
68   0,0,2,2,         4,4,118,118,     8,9,10,11,       12,13,14,15,
69   16,16,18,18,     20,21,22,23,     24,25,26,27,     28,28,118,28,
70   0,16,2,18,       36,37,37,37,     147,41,42,43,    44,45,128,128,
71   128,148,148,148, 45,45,45,148,    0,153,153,59,    60,61,62,63,
72
73   64,65,66,153,    153,153,153,153, 153,153,153,153, 153,153,153,153,
74   153,153,153,153, 153,153,153,153, 153,153,153,153, 153,153,153,153,
75   153,153,153,153, 153,153,153,153, 153,153,153,153, 153,153,153,153,
76   153,118,114,115, 131,118,118,119, 120,121,122,118, 118,118,118,118,
77
78   128,129,130,131, 132,133,134,135, 136,137,138,139, 140,141,142,143,
79   144,145,146,147, 148,149,150,151, 152,68,154,155,  156,157,158,160,
80   160,160,160,160, 160,160,160,160, 160,160,160,160, 160,160,160,175,
81   153,153,153,153, 153,153,153,153, 153,153,153,153, 153,153,68,153,
82
83   153,153,153,153, 153,153,153,153, 200,201,202,203, 204,205,206,207,
84   208,209,210,211, 212,213,214,215, 216,217,218,219, 220,221,222,223,
85   224,225,226,227, 228,229,230,231, 232,233,234,235, 236,237,238,239,
86   240,241,153,153, 153,153,153,153, 153,153,153,153, 153,153,153,153
87 };
88
89 static unsigned char remap_v4eater[28] =
90 {
91   /* filter crap for v4 */
92
93   128,18,2,0,4,8,16,20,28,37,
94   41,45,130,129,131,132,133,134,135,136,
95   146,147,175,65,66,64,2,18
96 };
97
98 static boolean filename_has_v1_format(char *filename)
99 {
100   char *basename = getBaseNamePtr(filename);
101
102   return (strlen(basename) == 3 &&
103           basename[0] == 'a' &&
104           basename[1] >= 'a' && basename[1] <= 'k' &&
105           basename[2] >= '0' && basename[2] <= '9');
106 }
107
108 int cleanup_em_level(unsigned char *src, int length, char *filename)
109 {
110   int file_version = FILE_VERSION_EM_UNKNOWN;
111   int i;
112
113   if (length >= 2172 &&
114       src[2106] == 255 &&               /* version id: */
115       src[2107] == 54 &&                /* '6' */
116       src[2108] == 48 &&                /* '0' */
117       src[2109] == 48)                  /* '0' */
118   {
119     /* ---------- this cave has V6 file format ---------- */
120     file_version = FILE_VERSION_EM_V6;
121
122     /* remap elements to internal EMC level format */
123     for (i = 0; i < 2048; i++)
124       src[i] = remap_v6[src[i]];
125     for (i = 2048; i < 2084; i++)
126       src[i] = remap_v6[src[i]];
127     for (i = 2112; i < 2148; i++)
128       src[i] = remap_v6[src[i]];
129   }
130   else if (length >= 2110 &&
131            src[2106] == 255 &&          /* version id: */
132            src[2107] == 53 &&           /* '5' */
133            src[2108] == 48 &&           /* '0' */
134            src[2109] == 48)             /* '0' */
135   {
136     /* ---------- this cave has V5 file format ---------- */
137     file_version = FILE_VERSION_EM_V5;
138
139     /* remap elements to internal EMC level format */
140     for (i = 0; i < 2048; i++)
141       src[i] = remap_v5[src[i]];
142     for (i = 2048; i < 2084; i++)
143       src[i] = remap_v5[src[i]];
144     for (i = 2112; i < 2148; i++)
145       src[i] = src[i - 64];
146   }
147   else if (length >= 2106 &&
148            (src[1983] == 27 ||          /* encrypted (only EM I/II/III) */
149             src[1983] == 116 ||         /* unencrypted (usual case) */
150             src[1983] == 131))          /* unencrypted (rare case) */
151   {
152     /* ---------- this cave has V1, V2 or V3 file format ---------- */
153
154     boolean fix_copyright = FALSE;
155
156     /*
157       byte at position 1983 (0x07bf) is used as "magic byte":
158       - 27  (0x1b)      => encrypted level (V3 only / Kingsoft original games)
159       - 116 (0x74)      => unencrypted level (byte is corrected to 131 (0x83))
160       - 131 (0x83)      => unencrypted level (happens only in very rare cases)
161     */
162
163     if (src[1983] == 27)        /* (0x1b) -- after decryption: 116 (0x74) */
164     {
165       /* this is original (encrypted) Emerald Mine I, II or III level file */
166
167       int first_byte = src[0];
168       unsigned char code0 = 0x65;
169       unsigned char code1 = 0x11;
170
171       /* decode encrypted level data */
172       for (i = 0; i < 2106; i++)
173       {
174         src[i] ^= code0;
175         src[i] -= code1;
176
177         code0 = (code0 + 7) & 0xff;
178       }
179
180       src[1] = 131;             /* needed for all Emerald Mine levels */
181
182       /* first byte is either 0xf1 (EM I and III) or 0xf5 (EM II) */
183       if (first_byte == 0xf5)
184       {
185         src[0] = 131;           /* only needed for Emerald Mine II levels */
186
187         fix_copyright = TRUE;
188       }
189
190       /* ---------- this cave has V3 file format ---------- */
191       file_version = FILE_VERSION_EM_V3;
192     }
193     else if (filename_has_v1_format(filename))
194     {
195       /* ---------- this cave has V1 file format ---------- */
196       file_version = FILE_VERSION_EM_V1;
197     }
198     else
199     {
200       /* ---------- this cave has V2 file format ---------- */
201       file_version = FILE_VERSION_EM_V2;
202     }
203
204     /* remap elements to internal EMC level format */
205     for (i = 0; i < 2048; i++)
206       src[i] = remap_v4[src[i]];
207     for (i = 2048; i < 2084; i++)
208       src[i] = remap_v4eater[src[i] >= 28 ? 0 : src[i]];
209     for (i = 2112; i < 2148; i++)
210       src[i] = src[i - 64];
211
212     if (fix_copyright)          /* fix "(c)" sign in Emerald Mine II levels */
213     {
214       for (i = 0; i < 2048; i++)
215         if (src[i] == 241)
216           src[i] = 254;         /* replace 'Xdecor_1' with 'Xalpha_copyr' */
217     }
218   }
219   else
220   {
221     /* ---------- this cave has unknown file format ---------- */
222
223     /* if file has length of old-style level file, print (wrong) magic byte */
224     if (length < 2110)
225       Error(ERR_WARN, "unknown magic byte 0x%02x at position 0x%04x",
226             src[1983], 1983);
227
228     return FILE_VERSION_EM_UNKNOWN;
229   }
230
231   if (file_version < FILE_VERSION_EM_V6)
232   {
233     /* id */
234     src[2106] = 255;            /* version id: */
235     src[2107] = 54;             /* '6' */
236     src[2108] = 48;             /* '0' */
237     src[2109] = 48;             /* '0' */
238
239     /* time */
240     i = src[2094] * 10;
241     /* stored level time of levels for the V2 player was changed to 50% of the
242        time for the V1 player (original V3 levels already considered this) */
243     if (file_version != FILE_VERSION_EM_V1 &&
244         file_version != FILE_VERSION_EM_V3)
245       i /= 2;
246     src[2110] = i >> 8;
247     src[2111] = i;
248
249     for (i = 2148; i < 2172; i++)
250       src[i] = 0;
251
252     /* ball data */
253     src[2159] = 128;
254   }
255
256   /* ---------- at this stage, the cave data always has V6 format ---------- */
257
258   /* fix wheel */
259   for (i = 0; i < 2048; i++)
260     if (src[i] == 40)
261       break;
262   for (i++; i < 2048; i++)
263     if (src[i] == 40)
264       src[i] = 147;
265
266 #if 0
267
268   /* fix acid */
269   for (i = 64; i < 2048; i++)
270     if (src[i] == 63)           /* replace element above 'Xacid_s' ... */
271       src[i - 64] = 101;        /* ... with 'Xacid_1' */
272
273 #else
274
275 #if 1
276   /* fix acid */
277   for (i = 64; i < 2048; i++)
278     if (src[i] == 63)           /* replace element above 'Xacid_s' ... */
279       src[i - 64] = 101;        /* ... with 'Xacid_1' */
280
281   /* fix acid with no base beneath it (see below for details (*)) */
282   for (i = 64; i < 2048 - 1; i++)
283   {
284     if (file_version <= FILE_VERSION_EM_V2 &&
285         src[i - 64] == 101 && src[i] != 63)     /* acid without base */
286     {
287       if (src[i - 1] == 101 ||                  /* remove acid over acid row */
288           src[i + 1] == 101)
289         src[i - 64] = 6;        /* replace element above with 'Xblank' */
290       else
291         src[i - 64] = 255;      /* replace element above with 'Xfake_acid_1' */
292     }
293   }
294
295 #else
296
297   /* fix acid */
298   for (i = 64; i < 2048; i++)
299   {
300     if (src[i] == 63)           /* 'Xacid_s' (acid pool, bottom middle) */
301     {
302       if (file_version <= FILE_VERSION_EM_V2 &&
303           i < 2048 - 64 && src[i + 64] == 63)
304       {
305         int obj_left  = remap_emerald[src[i - 1]];
306         int obj_right = remap_emerald[src[i + 1]];
307
308         if (obj_left == Xblank || obj_right == Xblank ||
309             obj_left == Xplant || obj_right == Xplant)
310           src[i - 64] = 6;      /* replace element above with 'Xblank' */
311         else
312           src[i - 64] = 255;    /* replace element above with 'Xfake_acid_1' */
313       }
314       else
315       {
316         src[i - 64] = 101;      /* replace element above with 'Xacid_1' */
317       }
318     }
319   }
320 #endif
321 #endif
322
323   /* fix acid in eater 1 */
324   for (i = 2051; i < 2057; i++)
325     if (src[i] == 63)
326       src[i - 3] = 101;
327
328   /* fix acid in eater 2 */
329   for (i = 2060; i < 2066; i++)
330     if (src[i] == 63)
331       src[i - 3] = 101;
332
333   /* fix acid in eater 3 */
334   for (i = 2069; i < 2075; i++)
335     if (src[i] == 63)
336       src[i - 3] = 101;
337
338   /* fix acid in eater 4 */
339   for (i = 2078; i < 2084; i++)
340     if (src[i] == 63)
341       src[i - 3] = 101;
342
343   /* fix acid in eater 5 */
344   for (i = 2115; i < 2121; i++)
345     if (src[i] == 63)
346       src[i - 3] = 101;
347
348   /* fix acid in eater 6 */
349   for (i = 2124; i < 2130; i++)
350     if (src[i] == 63)
351       src[i - 3] = 101;
352
353   /* fix acid in eater 7 */
354   for (i = 2133; i < 2139; i++)
355     if (src[i] == 63)
356       src[i - 3] = 101;
357
358   /* fix acid in eater 8 */
359   for (i = 2142; i < 2148; i++)
360     if (src[i] == 63)
361       src[i - 3] = 101;
362
363   /* old style time */
364   src[2094] = 0;
365
366   /* player 1 pos */
367   src[2096] &= 7;
368   src[src[2096] << 8 | src[2097]] = 128;
369
370   /* player 2 pos */
371   src[2098] &= 7;
372   src[src[2098] << 8 | src[2099]] = 128;
373
374   /* amoeba speed */
375   if ((src[2100] << 8 | src[2101]) > 9999)
376   {
377     src[2100] = 39;
378     src[2101] = 15;
379   }
380
381   /* time wonderwall */
382   if ((src[2102] << 8 | src[2103]) > 9999)
383   {
384     src[2102] = 39;
385     src[2103] = 15;
386   }
387
388   /* time */
389   if ((src[2110] << 8 | src[2111]) > 9999)
390   {
391     src[2110] = 39;
392     src[2111] = 15;
393   }
394
395   /* wind direction */
396   i = src[2149];
397   i &= 15;
398   i &= -i;
399   src[2149] = i;
400
401   /* time lenses */
402   if ((src[2154] << 8 | src[2155]) > 9999)
403   {
404     src[2154] = 39;
405     src[2155] = 15;
406   }
407
408   /* time magnify */
409   if ((src[2156] << 8 | src[2157]) > 9999)
410   {
411     src[2156] = 39;
412     src[2157] = 15;
413   }
414
415   /* ball object */
416   src[2158] = 0;
417   src[2159] = remap_v6[src[2159]];
418
419   /* ball pause */
420   if ((src[2160] << 8 | src[2161]) > 9999)
421   {
422     src[2160] = 39;
423     src[2161] = 15;
424   }
425
426   /* ball data */
427   src[2162] &= 129;
428   if (src[2162] & 1)
429     src[2163] = 0;
430
431   /* android move pause */
432   if ((src[2164] << 8 | src[2165]) > 9999)
433   {
434     src[2164] = 39;
435     src[2165] = 15;
436   }
437
438   /* android clone pause */
439   if ((src[2166] << 8 | src[2167]) > 9999)
440   {
441     src[2166] = 39;
442     src[2167] = 15;
443   }
444
445   /* android data */
446   src[2168] &= 31;
447
448   /* size of v6 cave */
449   length = 2172;
450
451 #if 0
452   if (options.debug)
453     Error(ERR_DEBUG, "EM level file version: %d", file_version);
454 #endif
455
456   return file_version;
457 }
458
459 /* 2000-07-30T00:26:00Z
460  *
461  * Read emerald mine caves version 6
462  *
463  * v4 and v5 emerald mine caves are converted to v6 (which completely supports
464  * older versions)
465  * 
466  * converting to the internal format loses /significant/ information which can
467  * break lots of caves.
468  * 
469  * major incompatibilities:
470  * - borderless caves behave completely differently, the player no longer
471  *   "warps" to the other side.
472  * - a compile time option for spring can make it behave differently when it
473  *   rolls.
474  * - a compile time option for rolling objects (stone, nut, spring, bomb) only
475  *   in eater.
476  * - acid is always deadly even with no base beneath it (this breaks cave 0 in
477  *   downunder mine 16)
478  *   (*) fixed (see above):
479  *       - downunder mine 16, level 0, works again
480  *       - downunder mine 11, level 71, corrected (only cosmetically)
481  *
482  * so far all below have not broken any caves:
483  *
484  * - active wheel inside an eater will not function, eater explosions will not
485  *   change settings.
486  * - initial collect objects (emerald, diamond, dynamite) don't exist.
487  * - initial rolling objects will be moved manually and made into sitting
488  *   objects.
489  * - drips always appear from dots.
490  * - more than one thing can fall into acid at the same time.
491  * - acid explodes when the player walks into it, rather than splashing.
492  * - simultaneous explosions may be in a slightly different order.
493  * - quicksand states have been reduced.
494  * - acid base is effectively an indestructable wall now which can affect eater
495  *   explosions.
496  * - android can clone forever with a clone pause of 0 (emeralds, diamonds,
497  *   nuts, stones, bombs, springs).
498  *
499  * 2001-03-12T02:46:55Z
500  * - rolling stuff is now allowed in the cave, i didn't like making this
501  *   decision.
502  * - if BAD_ROLL is not defined, initial rolling objects are moved by hand.
503  * - initial collect objects break some cave in elvis mine 5.
504  * - different timing for wonderwall break some cave in exception mine 2.
505  * - i think i'm pretty locked into always using the bad roll. *sigh*
506  * - rolling spring is now turned into regular spring. it appears the emc
507  *   editor only uses the force code for initially moving spring. i will
508  *   follow this in my editor.
509  *
510  * 2006-04-02
511  * - introduced ALLOW_ROLLING_SPRING; if defined, do NOT turn rolling spring
512  *   into regular spring, because this breaks at least E.M.C. Mine 3, level 79
513  *   (see comment directly above)
514  *
515  * 2020-01-19
516  * - always use BAD_ROLL and ALLOW_ROLLING_SPRING code when converting caves
517  *   (that is, always allow initial rolling objects in caves now)
518  */
519
520 static unsigned short remap_emerald[256] =
521 {
522   Xstone,               Xstone,         Xdiamond,       Xdiamond,
523   Xalien,               Xalien,         Xblank,         Xblank,
524   Xtank_1_n,            Xtank_1_e,      Xtank_1_s,      Xtank_1_w,
525   Xtank_2_n,            Xtank_2_e,      Xtank_2_s,      Xtank_2_w,
526
527   Xbomb,                Xbomb,          Xemerald,       Xemerald,
528   Xbug_1_n,             Xbug_1_e,       Xbug_1_s,       Xbug_1_w,
529   Xbug_2_n,             Xbug_2_e,       Xbug_2_s,       Xbug_2_w,
530   Xdrip,                Xdrip,          Xdrip,          Xdrip,
531
532   Xstone,               Xbomb,          Xdiamond,       Xemerald,
533   Xwonderwall,          Xnut,           Xnut,           Xnut,
534   Xwheel,               Xeater_n,       Xeater_s,       Xeater_w,
535   Xeater_e,             Xsand_stone,    Xblank,         Xblank,
536
537   Xblank,               Xsand,          Xsand,          Xsand,
538   Xsand_stone,          Xsand_stone,    Xsand_stone,    Xsand,
539   Xstone,               Xslidewall_ew,  Xslidewall_ns,  Xdynamite_1,
540   Xdynamite_2,          Xdynamite_3,    Xdynamite_4,    Xacid_s,
541
542   Xexit_1,              Xexit_2,        Xexit_3,        Xballoon,
543   Xplant,               Xspring,        Xspring_fall,   Xspring_w,
544   Xspring_e,            Xball_1,        Xball_2,        Xandroid,
545   Xblank,               Xandroid,       Xandroid,       Xandroid,
546
547   Xandroid,             Xandroid,       Xandroid,       Xandroid,
548   Xandroid,             Xblank,         Xblank,         Xblank,
549   Xblank,               Xblank,         Xblank,         Xblank,
550   Xblank,               Xblank,         Xblank,         Xblank,
551
552   Xblank,               Xblank,         Xblank,         Xpush_spring_w,
553   Xpush_spring_e,       Xacid_1,        Xacid_2,        Xacid_3,
554   Xacid_4,              Xacid_5,        Xacid_6,        Xacid_7,
555   Xacid_8,              Xblank,         Xblank,         Xblank,
556
557   Xblank,               Xblank,         Xpush_nut_w,    Xpush_nut_e,
558   Xsteel_1,             Xblank,         Xblank,         Xpush_bomb_w,
559   Xpush_bomb_e,         Xpush_stone_w,  Xpush_stone_e,  Xblank,
560   Xblank,               Xblank,         Xblank,         Xblank,
561
562   Xblank,               Xroundwall_1,   Xgrass,         Xsteel_1,
563   Xwall_1,              Xkey_1,         Xkey_2,         Xkey_3,
564   Xkey_4,               Xdoor_1,        Xdoor_2,        Xdoor_3,
565   Xdoor_4,              Xfake_amoeba,   Xfake_door_1,   Xfake_door_2,
566
567   Xfake_door_3,         Xfake_door_4,   Xwonderwall,    Xwheel,
568   Xsand,                Xacid_nw,       Xacid_ne,       Xacid_sw,
569   Xacid_se,             Xfake_blank,    Xamoeba_1,      Xamoeba_2,
570   Xamoeba_3,            Xamoeba_4,      Xexit,          Xalpha_arrow_w,
571
572   Xfake_grass,          Xlenses,        Xmagnify,       Xfake_blank,
573   Xfake_grass,          Xswitch,        Xswitch,        Xblank,
574   Xdecor_8,             Xdecor_9,       Xdecor_10,      Xdecor_5,
575   Xalpha_comma,         Xalpha_quote,   Xalpha_minus,   Xdynamite,
576
577   Xsteel_3,             Xdecor_6,       Xdecor_7,       Xsteel_2,
578   Xroundwall_2,         Xdecor_2,       Xdecor_4,       Xdecor_3,
579   Xwind_any,            Xwind_e,        Xwind_s,        Xwind_w,
580   Xwind_n,              Xdirt,          Xplant,         Xkey_5,
581
582   Xkey_6,               Xkey_7,         Xkey_8,         Xdoor_5,
583   Xdoor_6,              Xdoor_7,        Xdoor_8,        Xbumper,
584   Xalpha_a,             Xalpha_b,       Xalpha_c,       Xalpha_d,
585   Xalpha_e,             Xalpha_f,       Xalpha_g,       Xalpha_h,
586
587   Xalpha_i,             Xalpha_j,       Xalpha_k,       Xalpha_l,
588   Xalpha_m,             Xalpha_n,       Xalpha_o,       Xalpha_p,
589   Xalpha_q,             Xalpha_r,       Xalpha_s,       Xalpha_t,
590   Xalpha_u,             Xalpha_v,       Xalpha_w,       Xalpha_x,
591
592   Xalpha_y,             Xalpha_z,       Xalpha_0,       Xalpha_1,
593   Xalpha_2,             Xalpha_3,       Xalpha_4,       Xalpha_5,
594   Xalpha_6,             Xalpha_7,       Xalpha_8,       Xalpha_9,
595   Xalpha_perio,         Xalpha_excla,   Xalpha_colon,   Xalpha_quest,
596
597   Xalpha_arrow_e,       Xdecor_1,       Xfake_door_5,   Xfake_door_6,
598   Xfake_door_7,         Xfake_door_8,   Xblank,         Xblank,
599   Xblank,               Xblank,         Xblank,         Xblank,
600 #if 0
601   Xblank,               Xblank,         Xblank,         Xblank,
602 #else
603   /* special elements added to solve compatibility problems */
604   Xblank,               Xblank,         Xalpha_copyr,   Xfake_acid_1
605 #endif
606 };
607
608 static int get_em_element(unsigned short em_element_raw, int file_version)
609 {
610   int em_element = remap_emerald[em_element_raw];
611
612   if (file_version < FILE_VERSION_EM_V5)
613   {
614     /* versions below V5 had no grass, but only sand/dirt */
615     if (em_element == Xgrass)
616       em_element = Xdirt;
617   }
618
619   return em_element;
620 }
621
622 void convert_em_level(unsigned char *src, int file_version)
623 {
624   static int eater_offset[8] =
625   {
626     0x800, 0x809, 0x812, 0x81B, 0x840, 0x849, 0x852, 0x85B
627   };
628   int i, x, y, temp;
629
630 #if 1
631   lev.time_seconds = src[0x83E] << 8 | src[0x83F];
632   if (lev.time_seconds > 9999)
633     lev.time_seconds = 9999;
634 #else
635   temp = ((src[0x83E] << 8 | src[0x83F]) * 25 + 3) / 4;
636   if (temp == 0 || temp > 9999)
637     temp = 9999;
638   lev.time_initial = temp;
639 #endif
640
641   lev.required_initial = src[0x82F];
642
643   for (i = 0; i < 2; i++)
644   {
645     temp = src[0x830 + i * 2] << 8 | src[0x831 + i * 2];
646     ply[i].x_initial = (temp & 63);
647     ply[i].y_initial = (temp >> 6 & 31);
648   }
649
650   temp = (src[0x834] << 8 | src[0x835]) * 28;
651   if (temp > 9999)
652     temp = 9999;
653   lev.amoeba_time = temp;
654
655   lev.android_move_time = src[0x874] << 8 | src[0x875];
656   lev.android_clone_time = src[0x876] << 8 | src[0x877];
657
658   lev.ball_random = src[0x872] & 1 ? 1 : 0;
659   lev.ball_state_initial = src[0x872] & 128 ? 1 : 0;
660   lev.ball_time = src[0x870] << 8 | src[0x871];
661
662   lev.emerald_score = src[0x824];
663   lev.diamond_score = src[0x825];
664   lev.alien_score = src[0x826];
665   lev.tank_score = src[0x827];
666   lev.bug_score = src[0x828];
667   lev.eater_score = src[0x829];
668   lev.nut_score = src[0x82A];
669   lev.dynamite_score = src[0x82B];
670   lev.key_score = src[0x82C];
671   lev.exit_score = src[0x82D] * 8 / 5;
672   lev.lenses_score = src[0x867];
673   lev.magnify_score = src[0x868];
674   lev.slurp_score = src[0x869];
675
676   lev.lenses_time = src[0x86A] << 8 | src[0x86B];
677   lev.magnify_time = src[0x86C] << 8 | src[0x86D];
678   lev.wheel_time = src[0x838] << 8 | src[0x839];
679
680   lev.wind_cnt_initial = src[0x865] & 15 ? lev.wind_time : 0;
681   temp = src[0x865];
682   lev.wind_direction_initial = (temp & 8 ? 0 :
683                                 temp & 1 ? 1 :
684                                 temp & 2 ? 2 :
685                                 temp & 4 ? 3 : 0);
686
687   lev.wonderwall_time_initial = src[0x836] << 8 | src[0x837];
688
689   for (i = 0; i < 8; i++)
690     for (x = 0; x < 9; x++)
691       lev.eater_array[i][x] =
692         get_em_element(src[eater_offset[i] + x], file_version);
693
694   temp = get_em_element(src[0x86F], file_version);
695   for (y = 0; y < 8; y++)
696   {
697     if (src[0x872] & 1)
698     {
699       for (x = 0; x < 8; x++)
700         lev.ball_array[y][x] = temp;
701     }
702     else
703     {
704       lev.ball_array[y][1] = (src[0x873] & 1)  ? temp : Xblank; /* north */
705       lev.ball_array[y][6] = (src[0x873] & 2)  ? temp : Xblank; /* south */
706       lev.ball_array[y][3] = (src[0x873] & 4)  ? temp : Xblank; /* west */
707       lev.ball_array[y][4] = (src[0x873] & 8)  ? temp : Xblank; /* east */
708       lev.ball_array[y][7] = (src[0x873] & 16) ? temp : Xblank; /* southeast */
709       lev.ball_array[y][5] = (src[0x873] & 32) ? temp : Xblank; /* southwest */
710       lev.ball_array[y][2] = (src[0x873] & 64) ? temp : Xblank; /* northeast */
711       lev.ball_array[y][0] = (src[0x873] & 128)? temp : Xblank; /* northwest */
712     }
713   }
714
715   temp = src[0x878] << 8 | src[0x879];
716
717   if (temp & 1)
718   {
719     lev.android_array[Xemerald]         = Xemerald;
720     lev.android_array[Xemerald_pause]   = Xemerald;
721     lev.android_array[Xemerald_fall]    = Xemerald;
722     lev.android_array[Yemerald_sB]      = Xemerald;
723     lev.android_array[Yemerald_eB]      = Xemerald;
724     lev.android_array[Yemerald_wB]      = Xemerald;
725   }
726
727   if (temp & 2)
728   {
729     lev.android_array[Xdiamond]         = Xdiamond;
730     lev.android_array[Xdiamond_pause]   = Xdiamond;
731     lev.android_array[Xdiamond_fall]    = Xdiamond;
732     lev.android_array[Ydiamond_sB]      = Xdiamond;
733     lev.android_array[Ydiamond_eB]      = Xdiamond;
734     lev.android_array[Ydiamond_wB]      = Xdiamond;
735   }
736
737   if (temp & 4)
738   {
739     lev.android_array[Xstone]           = Xstone;
740     lev.android_array[Xstone_pause]     = Xstone;
741     lev.android_array[Xstone_fall]      = Xstone;
742     lev.android_array[Ystone_sB]        = Xstone;
743     lev.android_array[Ystone_eB]        = Xstone;
744     lev.android_array[Ystone_wB]        = Xstone;
745   }
746
747   if (temp & 8)
748   {
749     lev.android_array[Xbomb]            = Xbomb;
750     lev.android_array[Xbomb_pause]      = Xbomb;
751     lev.android_array[Xbomb_fall]       = Xbomb;
752     lev.android_array[Ybomb_sB]         = Xbomb;
753     lev.android_array[Ybomb_eB]         = Xbomb;
754     lev.android_array[Ybomb_wB]         = Xbomb;
755   }
756
757   if (temp & 16)
758   {
759     lev.android_array[Xnut]             = Xnut;
760     lev.android_array[Xnut_pause]       = Xnut;
761     lev.android_array[Xnut_fall]        = Xnut;
762     lev.android_array[Ynut_sB]          = Xnut;
763     lev.android_array[Ynut_eB]          = Xnut;
764     lev.android_array[Ynut_wB]          = Xnut;
765   }
766
767   if (temp & 32)
768   {
769     lev.android_array[Xtank_1_n]        = Xtank_1_n;
770     lev.android_array[Xtank_2_n]        = Xtank_1_n;
771     lev.android_array[Ytank_nB]         = Xtank_1_n;
772     lev.android_array[Ytank_n_e]        = Xtank_1_n;
773     lev.android_array[Ytank_n_w]        = Xtank_1_n;
774
775     lev.android_array[Xtank_1_e]        = Xtank_1_e;
776     lev.android_array[Xtank_2_e]        = Xtank_1_e;
777     lev.android_array[Ytank_eB]         = Xtank_1_e;
778     lev.android_array[Ytank_e_s]        = Xtank_1_e;
779     lev.android_array[Ytank_e_n]        = Xtank_1_e;
780
781     lev.android_array[Xtank_1_s]        = Xtank_1_s;
782     lev.android_array[Xtank_2_s]        = Xtank_1_s;
783     lev.android_array[Ytank_sB]         = Xtank_1_s;
784     lev.android_array[Ytank_s_w]        = Xtank_1_s;
785     lev.android_array[Ytank_s_e]        = Xtank_1_s;
786
787     lev.android_array[Xtank_1_w]        = Xtank_1_w;
788     lev.android_array[Xtank_2_w]        = Xtank_1_w;
789     lev.android_array[Ytank_wB]         = Xtank_1_w;
790     lev.android_array[Ytank_w_n]        = Xtank_1_w;
791     lev.android_array[Ytank_w_s]        = Xtank_1_w;
792   }
793
794   if (temp & 64)
795   {
796     lev.android_array[Xeater_n]         = Xeater_n;
797     lev.android_array[Yeater_nB]        = Xeater_n;
798
799     lev.android_array[Xeater_e]         = Xeater_e;
800     lev.android_array[Yeater_eB]        = Xeater_e;
801
802     lev.android_array[Xeater_s]         = Xeater_s;
803     lev.android_array[Yeater_sB]        = Xeater_s;
804
805     lev.android_array[Xeater_w]         = Xeater_w;
806     lev.android_array[Yeater_wB]        = Xeater_w;
807   }
808
809   if (temp & 128)
810   {
811     lev.android_array[Xbug_1_n]         = Xbug_2_n;
812     lev.android_array[Xbug_2_n]         = Xbug_2_n;
813     lev.android_array[Ybug_nB]          = Xbug_2_n;
814     lev.android_array[Ybug_n_e]         = Xbug_2_n;
815     lev.android_array[Ybug_n_w]         = Xbug_2_n;
816
817     lev.android_array[Xbug_1_e]         = Xbug_2_e;
818     lev.android_array[Xbug_2_e]         = Xbug_2_e;
819     lev.android_array[Ybug_eB]          = Xbug_2_e;
820     lev.android_array[Ybug_e_s]         = Xbug_2_e;
821     lev.android_array[Ybug_e_n]         = Xbug_2_e;
822
823     lev.android_array[Xbug_1_s]         = Xbug_2_s;
824     lev.android_array[Xbug_2_s]         = Xbug_2_s;
825     lev.android_array[Ybug_sB]          = Xbug_2_s;
826     lev.android_array[Ybug_s_w]         = Xbug_2_s;
827     lev.android_array[Ybug_s_e]         = Xbug_2_s;
828
829     lev.android_array[Xbug_1_w]         = Xbug_2_w;
830     lev.android_array[Xbug_2_w]         = Xbug_2_w;
831     lev.android_array[Ybug_wB]          = Xbug_2_w;
832     lev.android_array[Ybug_w_n]         = Xbug_2_w;
833     lev.android_array[Ybug_w_s]         = Xbug_2_w;
834   }
835
836   if (temp & 256)
837   {
838     lev.android_array[Xalien]           = Xalien;
839     lev.android_array[Xalien_pause]     = Xalien;
840     lev.android_array[Yalien_nB]        = Xalien;
841     lev.android_array[Yalien_eB]        = Xalien;
842     lev.android_array[Yalien_sB]        = Xalien;
843     lev.android_array[Yalien_wB]        = Xalien;
844   }
845
846   if (temp & 512)
847   {
848     lev.android_array[Xspring]          = Xspring;
849     lev.android_array[Xspring_pause]    = Xspring;
850     lev.android_array[Xspring_e]        = Xspring;
851     lev.android_array[Yspring_eB]       = Xspring;
852     lev.android_array[Yspring_alien_eB] = Xspring;
853     lev.android_array[Xspring_w]        = Xspring;
854     lev.android_array[Yspring_wB]       = Xspring;
855     lev.android_array[Yspring_alien_wB] = Xspring;
856     lev.android_array[Xspring_fall]     = Xspring;
857     lev.android_array[Yspring_sB]       = Xspring;
858   }
859
860   if (temp & 1024)
861   {
862     lev.android_array[Yballoon_nB]      = Xballoon;
863     lev.android_array[Yballoon_eB]      = Xballoon;
864     lev.android_array[Yballoon_sB]      = Xballoon;
865     lev.android_array[Yballoon_wB]      = Xballoon;
866     lev.android_array[Xballoon]         = Xballoon;
867   }
868
869   if (temp & 2048)
870   {
871     lev.android_array[Xfake_amoeba]     = Xdrip;
872     lev.android_array[Xfake_amoebaB]    = Xdrip;
873     lev.android_array[Xamoeba_1]        = Xdrip;
874     lev.android_array[Xamoeba_2]        = Xdrip;
875     lev.android_array[Xamoeba_3]        = Xdrip;
876     lev.android_array[Xamoeba_4]        = Xdrip;
877     lev.android_array[Xamoeba_5]        = Xdrip;
878     lev.android_array[Xamoeba_6]        = Xdrip;
879     lev.android_array[Xamoeba_7]        = Xdrip;
880     lev.android_array[Xamoeba_8]        = Xdrip;
881   }
882
883   if (temp & 4096)
884   {
885     lev.android_array[Xdynamite]        = Xdynamite;
886   }
887
888   for (temp = 1; temp < 2047; temp++)
889   {
890     switch (src[temp])
891     {
892       case 0x24:                                /* wonderwall */
893         lev.wonderwall_state_initial = 1;
894         lev.wonderwall_time_initial = 9999;
895         break;
896
897       case 0x28:                                /* wheel */
898         lev.wheel_x_initial = temp & 63;
899         lev.wheel_y_initial = temp >> 6;
900         lev.wheel_cnt_initial = lev.wheel_time;
901         break;
902
903       case 0xA3:                                /* fake blank */
904         lev.lenses_cnt_initial = 9999;
905         break;
906
907       case 0xA4:                                /* fake grass */
908         lev.magnify_cnt_initial = 9999;
909         break;
910     }
911   }
912
913   /* first fill the complete playfield with the default border element */
914   for (y = 0; y < CAVE_HEIGHT; y++)
915     for (x = 0; x < CAVE_WIDTH; x++)
916       native_em_level.cave[x][y] = Zborder;
917
918   /* then copy the real level contents from level file into the playfield */
919   temp = 0;
920   for (y = 0; y < lev.height; y++)
921     for (x = 0; x < lev.width; x++)
922       native_em_level.cave[x][y] =
923         get_em_element(src[temp++], file_version);
924
925   /* at last, set the two players at their positions in the playfield */
926   /* (native EM[C] levels always have exactly two players in a level) */
927   for (i = 0; i < 2; i++)
928     native_em_level.cave[ply[i].x_initial][ply[i].y_initial] = Zplayer;
929
930   native_em_level.file_version = file_version;
931 }
932
933 void prepare_em_level(void)
934 {
935   int i, x, y;
936   int players_left;
937   boolean team_mode;
938
939   /* reset all runtime variables to their initial values */
940
941   lev.left = CAVE_BUFFER_XOFFSET;
942   lev.top  = CAVE_BUFFER_YOFFSET;
943   lev.right = lev.left + lev.width;
944   lev.bottom = lev.top + lev.height;
945
946   for (y = 0; y < CAVE_HEIGHT; y++)
947     for (x = 0; x < CAVE_WIDTH; x++)
948       lev.cave[lev.left + x][lev.top + y] = native_em_level.cave[x][y];
949
950   for (y = 0; y < CAVE_BUFFER_HEIGHT; y++)
951     for (x = 0; x < CAVE_BUFFER_WIDTH; x++)
952       lev.next[x][y] = lev.cave[x][y];
953
954   for (y = 0; y < CAVE_BUFFER_HEIGHT; y++)
955     for (x = 0; x < CAVE_BUFFER_WIDTH; x++)
956       lev.draw[x][y] = lev.cave[x][y];
957
958   lev.time_initial = lev.time_seconds;
959   lev.time = lev.time_initial;
960
961   lev.required = lev.required_initial;
962   lev.score = 0;
963
964   lev.android_move_cnt  = lev.android_move_time;
965   lev.android_clone_cnt = lev.android_clone_time;
966
967   lev.ball_pos = 0;
968   lev.ball_state = lev.ball_state_initial;
969   lev.ball_cnt = lev.ball_time;
970
971   lev.eater_pos = 0;
972   lev.shine_cnt = 0;
973
974   lev.lenses_cnt = lev.lenses_cnt_initial;
975   lev.magnify_cnt = lev.magnify_cnt_initial;
976
977   lev.wheel_cnt = lev.wheel_cnt_initial;
978   lev.wheel_x   = lev.wheel_x_initial;
979   lev.wheel_y   = lev.wheel_y_initial;
980
981   lev.wind_direction = lev.wind_direction_initial;
982   lev.wind_cnt       = lev.wind_cnt_initial;
983
984   lev.wonderwall_state = lev.wonderwall_state_initial;
985   lev.wonderwall_time  = lev.wonderwall_time_initial;
986
987   lev.killed_out_of_time = FALSE;
988
989   /* determine number of players in this level */
990   lev.home_initial = 0;
991
992   for (i = 0; i < MAX_PLAYERS; i++)
993   {
994     ply[i].exists = 0;
995     ply[i].alive_initial = FALSE;
996
997     if (ply[i].x_initial != -1 && ply[i].y_initial != -1)
998     {
999       ply[i].exists = 1;
1000
1001       lev.home_initial++;
1002     }
1003   }
1004
1005   team_mode = getTeamMode_EM();
1006
1007   if (!team_mode)
1008     lev.home_initial = 1;
1009
1010   lev.home = lev.home_initial;
1011   players_left = lev.home_initial;
1012
1013   for (i = 0; i < MAX_PLAYERS; i++)
1014   {
1015     if (ply[i].exists)
1016     {
1017       if (players_left)
1018       {
1019         ply[i].alive_initial = TRUE;
1020         players_left--;
1021       }
1022       else
1023       {
1024         int x = ply[i].x_initial;
1025         int y = ply[i].y_initial;
1026
1027         native_em_level.cave[x][y] = Xblank;
1028
1029         lev.cave[lev.left + x][lev.top + y] = Xblank;
1030         lev.next[lev.left + x][lev.top + y] = Xblank;
1031         lev.draw[lev.left + x][lev.top + y] = Xblank;
1032       }
1033     }
1034   }
1035
1036   for (i = 0; i < MAX_PLAYERS; i++)
1037   {
1038     ply[i].num = i;
1039     ply[i].alive = ply[i].alive_initial;
1040     ply[i].dynamite = 0;
1041     ply[i].dynamite_cnt = 0;
1042     ply[i].keys = 0;
1043     ply[i].anim = 0;
1044     ply[i].oldx = ply[i].x = ply[i].x_initial + lev.left;
1045     ply[i].oldy = ply[i].y = ply[i].y_initial + lev.top;
1046     ply[i].last_move_dir = MV_NONE;
1047     ply[i].joy_n = ply[i].joy_e = ply[i].joy_s = ply[i].joy_w = 0;
1048     ply[i].joy_snap  = ply[i].joy_drop = 0;
1049     ply[i].joy_stick = ply[i].joy_spin = 0;
1050   }
1051
1052   // the following engine variables are initialized to version-specific values
1053   // in function InitGameEngine() (src/game.c):
1054   //
1055   // - game_em.use_single_button (default: TRUE)
1056   // - game_em.use_snap_key_bug (default: FALSE)
1057
1058   game_em.level_solved = FALSE;
1059   game_em.game_over = FALSE;
1060
1061   game_em.any_player_moving = FALSE;
1062   game_em.any_player_snapping = FALSE;
1063
1064   game_em.last_moving_player = 0;       /* default: first player */
1065
1066   for (i = 0; i < MAX_PLAYERS; i++)
1067     game_em.last_player_direction[i] = MV_NONE;
1068
1069   lev.exit_x = lev.exit_y = -1; /* kludge for playing player exit sound */
1070 }