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