086bc7a3ea37cc80084ce83ba6af0e10a924eda7
[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 (options.debug)
458     printf("::: EM level file version: %d\n", file_version);
459
460   return file_version;
461 }
462
463 /* 2000-07-30T00:26:00Z
464  *
465  * Read emerald mine caves version 6
466  *
467  * v4 and v5 emerald mine caves are converted to v6 (which completely supports
468  * older versions)
469  * 
470  * converting to the internal format loses /significant/ information which can
471  * break lots of caves.
472  * 
473  * major incompatibilities:
474  * - borderless caves behave completely differently, the player no longer
475  *   "warps" to the other side.
476  * - a compile time option for spring can make it behave differently when it
477  *   rolls.
478  * - a compile time option for rolling objects (stone, nut, spring, bomb) only
479  *   in eater.
480  * - acid is always deadly even with no base beneath it (this breaks cave 0 in
481  *   downunder mine 16)
482  *   (*) fixed (see above):
483  *       - downunder mine 16, level 0, works again
484  *       - downunder mine 11, level 71, corrected (only cosmetically)
485  *
486  * so far all below have not broken any caves:
487  *
488  * - active wheel inside an eater will not function, eater explosions will not
489  *   change settings.
490  * - initial collect objects (emerald, diamond, dynamite) don't exist.
491  * - initial rolling objects will be moved manually and made into sitting
492  *   objects.
493  * - drips always appear from dots.
494  * - more than one thing can fall into acid at the same time.
495  * - acid explodes when the player walks into it, rather than splashing.
496  * - simultaneous explosions may be in a slightly different order.
497  * - quicksand states have been reduced.
498  * - acid base is effectively an indestructable wall now which can affect eater
499  *   explosions.
500  * - android can clone forever with a clone pause of 0 (emeralds, diamonds,
501  *   nuts, stones, bombs, springs).
502  *
503  * 2001-03-12T02:46:55Z
504  * - rolling stuff is now allowed in the cave, i didn't like making this
505  *   decision.
506  * - if BAD_ROLL is not defined, initial rolling objects are moved by hand.
507  * - initial collect objects break some cave in elvis mine 5.
508  * - different timing for wonderwall break some cave in exception mine 2.
509  * - i think i'm pretty locked into always using the bad roll. *sigh*
510  * - rolling spring is now turned into regular spring. it appears the emc
511  *   editor only uses the force code for initially moving spring. i will
512  *   follow this in my editor.
513  *
514  * 2006-04-02
515  * - introduced ALLOW_ROLLING_SPRING; if defined, do NOT turn rolling spring
516  *   into regular spring, because this breaks at least E.M.C. Mine 3, level 79
517  *   (see comment directly above)
518  */
519
520 static unsigned short remap_emerald[256] =
521 {
522   Xstone,               Xstone,         Xdiamond,       Xdiamond,
523   Xalien,               Xalien,         Xblank,         Xblank,
524   Xtank_n,              Xtank_e,        Xtank_s,        Xtank_w,
525   Xtank_gon,            Xtank_goe,      Xtank_gos,      Xtank_gow,
526
527   Xbomb,                Xbomb,          Xemerald,       Xemerald,
528   Xbug_n,               Xbug_e,         Xbug_s,         Xbug_w,
529   Xbug_gon,             Xbug_goe,       Xbug_gos,       Xbug_gow,
530   Xdrip_eat,            Xdrip_eat,      Xdrip_eat,      Xdrip_eat,
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,               Xgrow_ew,       Xgrow_ns,       Xdynamite_1,
540   Xdynamite_2,          Xdynamite_3,    Xdynamite_4,    Xacid_s,
541
542 #ifdef ALLOW_ROLLING_SPRING
543   Xexit_1,              Xexit_2,        Xexit_3,        Xballoon,
544   Xplant,               Xspring,        Xspring_fall,   Xspring_w,
545   Xspring_e,            Xball_1,        Xball_2,        Xandroid,
546   Xblank,               Xandroid,       Xandroid,       Xandroid,
547 #else
548   Xexit_1,              Xexit_2,        Xexit_3,        Xballoon,
549   Xplant,               Xspring,        Xspring,        Xspring,
550   Xspring,              Xball_1,        Xball_2,        Xandroid,
551   Xblank,               Xandroid,       Xandroid,       Xandroid,
552 #endif
553
554   Xandroid,             Xandroid,       Xandroid,       Xandroid,
555   Xandroid,             Xblank,         Xblank,         Xblank,
556   Xblank,               Xblank,         Xblank,         Xblank,
557   Xblank,               Xblank,         Xblank,         Xblank,
558
559 #ifdef BAD_ROLL
560
561   Xblank,               Xblank,         Xblank,         Xspring_force_w,
562   Xspring_force_e,      Xacid_1,        Xacid_2,        Xacid_3,
563   Xacid_4,              Xacid_5,        Xacid_6,        Xacid_7,
564   Xacid_8,              Xblank,         Xblank,         Xblank,
565
566   Xblank,               Xblank,         Xnut_force_w,   Xnut_force_e,
567   Xsteel_1,             Xblank,         Xblank,         Xbomb_force_w,
568   Xbomb_force_e,        Xstone_force_w, Xstone_force_e, Xblank,
569   Xblank,               Xblank,         Xblank,         Xblank,
570
571 #else
572
573   Xblank,               Xblank,         Xblank,         Xspring,
574   Xspring,              Xacid_1,        Xacid_2,        Xacid_3,
575   Xacid_4,              Xacid_5,        Xacid_6,        Xacid_7,
576   Xacid_8,              Xblank,         Xblank,         Xblank,
577
578   Xblank,               Xblank,         Xnut,           Xnut,
579   Xsteel_1,             Xblank,         Xblank,         Xbomb,
580   Xbomb,                Xstone,         Xstone,         Xblank,
581   Xblank,               Xblank,         Xblank,         Xblank,
582
583 #endif
584
585   Xblank,               Xround_wall_1,  Xgrass,         Xsteel_1,
586   Xwall_1,              Xkey_1,         Xkey_2,         Xkey_3,
587   Xkey_4,               Xdoor_1,        Xdoor_2,        Xdoor_3,
588   Xdoor_4,              Xdripper,       Xfake_door_1,   Xfake_door_2,
589
590   Xfake_door_3,         Xfake_door_4,   Xwonderwall,    Xwheel,
591   Xsand,                Xacid_nw,       Xacid_ne,       Xacid_sw,
592   Xacid_se,             Xfake_blank,    Xamoeba_1,      Xamoeba_2,
593   Xamoeba_3,            Xamoeba_4,      Xexit,          Xalpha_arrow_w,
594
595   Xfake_grass,          Xlenses,        Xmagnify,       Xfake_blank,
596   Xfake_grass,          Xswitch,        Xswitch,        Xblank,
597   Xdecor_8,             Xdecor_9,       Xdecor_10,      Xdecor_5,
598   Xalpha_comma,         Xalpha_quote,   Xalpha_minus,   Xdynamite,
599
600   Xsteel_3,             Xdecor_6,       Xdecor_7,       Xsteel_2,
601   Xround_wall_2,        Xdecor_2,       Xdecor_4,       Xdecor_3,
602   Xwind_nesw,           Xwind_e,        Xwind_s,        Xwind_w,
603   Xwind_n,              Xdirt,          Xplant,         Xkey_5,
604
605   Xkey_6,               Xkey_7,         Xkey_8,         Xdoor_5,
606   Xdoor_6,              Xdoor_7,        Xdoor_8,        Xbumper,
607   Xalpha_a,             Xalpha_b,       Xalpha_c,       Xalpha_d,
608   Xalpha_e,             Xalpha_f,       Xalpha_g,       Xalpha_h,
609
610   Xalpha_i,             Xalpha_j,       Xalpha_k,       Xalpha_l,
611   Xalpha_m,             Xalpha_n,       Xalpha_o,       Xalpha_p,
612   Xalpha_q,             Xalpha_r,       Xalpha_s,       Xalpha_t,
613   Xalpha_u,             Xalpha_v,       Xalpha_w,       Xalpha_x,
614
615   Xalpha_y,             Xalpha_z,       Xalpha_0,       Xalpha_1,
616   Xalpha_2,             Xalpha_3,       Xalpha_4,       Xalpha_5,
617   Xalpha_6,             Xalpha_7,       Xalpha_8,       Xalpha_9,
618   Xalpha_perio,         Xalpha_excla,   Xalpha_colon,   Xalpha_quest,
619
620   Xalpha_arrow_e,       Xdecor_1,       Xfake_door_5,   Xfake_door_6,
621   Xfake_door_7,         Xfake_door_8,   Xblank,         Xblank,
622   Xblank,               Xblank,         Xblank,         Xblank,
623 #if 0
624   Xblank,               Xblank,         Xblank,         Xblank,
625 #else
626   /* special elements added to solve compatibility problems */
627   Xblank,               Xblank,         Xalpha_copyr,   Xfake_acid_1
628 #endif
629 };
630
631 static int get_em_element(unsigned short em_element_raw, int file_version)
632 {
633   int em_element = remap_emerald[em_element_raw];
634
635   if (file_version < FILE_VERSION_EM_V5)
636   {
637     /* versions below V5 had no grass, but only sand/dirt */
638     if (em_element == Xgrass)
639       em_element = Xdirt;
640   }
641
642   return em_element;
643 }
644
645 void convert_em_level(unsigned char *src, int file_version)
646 {
647   static int eater_offset[8] =
648   {
649     0x800, 0x809, 0x812, 0x81B, 0x840, 0x849, 0x852, 0x85B
650   };
651   int i, x, y, temp;
652
653 #if 1
654   lev.time_seconds = src[0x83E] << 8 | src[0x83F];
655   if (lev.time_seconds > 9999)
656     lev.time_seconds = 9999;
657 #else
658   temp = ((src[0x83E] << 8 | src[0x83F]) * 25 + 3) / 4;
659   if (temp == 0 || temp > 9999)
660     temp = 9999;
661   lev.time_initial = temp;
662 #endif
663
664   lev.required_initial = src[0x82F];
665
666   for (i = 0; i < 2; i++)
667   {
668     temp = src[0x830 + i * 2] << 8 | src[0x831 + i * 2];
669     ply[i].x_initial = (temp & 63) + 1;
670     ply[i].y_initial = (temp >> 6 & 31) + 1;
671   }
672
673   temp = (src[0x834] << 8 | src[0x835]) * 28;
674   if (temp > 9999)
675     temp = 9999;
676   lev.amoeba_time = temp;
677
678   lev.android_move_time = src[0x874] << 8 | src[0x875];
679   lev.android_clone_time = src[0x876] << 8 | src[0x877];
680
681   lev.ball_random = src[0x872] & 1 ? 1 : 0;
682   lev.ball_state_initial = src[0x872] & 128 ? 1 : 0;
683   lev.ball_time = src[0x870] << 8 | src[0x871];
684
685   lev.emerald_score = src[0x824];
686   lev.diamond_score = src[0x825];
687   lev.alien_score = src[0x826];
688   lev.tank_score = src[0x827];
689   lev.bug_score = src[0x828];
690   lev.eater_score = src[0x829];
691   lev.nut_score = src[0x82A];
692   lev.dynamite_score = src[0x82B];
693   lev.key_score = src[0x82C];
694   lev.exit_score = src[0x82D] * 8 / 5;
695   lev.lenses_score = src[0x867];
696   lev.magnify_score = src[0x868];
697   lev.slurp_score = src[0x869];
698
699   lev.lenses_time = src[0x86A] << 8 | src[0x86B];
700   lev.magnify_time = src[0x86C] << 8 | src[0x86D];
701   lev.wheel_time = src[0x838] << 8 | src[0x839];
702
703   lev.wind_cnt_initial = src[0x865] & 15 ? lev.wind_time : 0;
704   temp = src[0x865];
705   lev.wind_direction_initial = (temp & 8 ? 0 :
706                                 temp & 1 ? 1 :
707                                 temp & 2 ? 2 :
708                                 temp & 4 ? 3 : 0);
709
710   lev.wonderwall_time_initial = src[0x836] << 8 | src[0x837];
711
712   for (i = 0; i < 8; i++)
713     for (x = 0; x < 9; x++)
714       lev.eater_array[i][x] =
715         get_em_element(src[eater_offset[i] + x], file_version);
716
717   temp = get_em_element(src[0x86F], file_version);
718   for (y = 0; y < 8; y++)
719   {
720     if (src[0x872] & 1)
721     {
722       for (x = 0; x < 8; x++)
723         lev.ball_array[y][x] = temp;
724     }
725     else
726     {
727       lev.ball_array[y][1] = (src[0x873] & 1)  ? temp : Xblank; /* north */
728       lev.ball_array[y][6] = (src[0x873] & 2)  ? temp : Xblank; /* south */
729       lev.ball_array[y][3] = (src[0x873] & 4)  ? temp : Xblank; /* west */
730       lev.ball_array[y][4] = (src[0x873] & 8)  ? temp : Xblank; /* east */
731       lev.ball_array[y][7] = (src[0x873] & 16) ? temp : Xblank; /* southeast */
732       lev.ball_array[y][5] = (src[0x873] & 32) ? temp : Xblank; /* southwest */
733       lev.ball_array[y][2] = (src[0x873] & 64) ? temp : Xblank; /* northeast */
734       lev.ball_array[y][0] = (src[0x873] & 128)? temp : Xblank; /* northwest */
735     }
736   }
737
738   temp = src[0x878] << 8 | src[0x879];
739
740   if (temp & 1)
741   {
742     lev.android_array[Xemerald]         = Xemerald;
743     lev.android_array[Xemerald_pause]   = Xemerald;
744     lev.android_array[Xemerald_fall]    = Xemerald;
745     lev.android_array[Yemerald_sB]      = Xemerald;
746     lev.android_array[Yemerald_eB]      = Xemerald;
747     lev.android_array[Yemerald_wB]      = Xemerald;
748   }
749
750   if (temp & 2)
751   {
752     lev.android_array[Xdiamond]         = Xdiamond;
753     lev.android_array[Xdiamond_pause]   = Xdiamond;
754     lev.android_array[Xdiamond_fall]    = Xdiamond;
755     lev.android_array[Ydiamond_sB]      = Xdiamond;
756     lev.android_array[Ydiamond_eB]      = Xdiamond;
757     lev.android_array[Ydiamond_wB]      = Xdiamond;
758   }
759
760   if (temp & 4)
761   {
762     lev.android_array[Xstone]           = Xstone;
763     lev.android_array[Xstone_pause]     = Xstone;
764     lev.android_array[Xstone_fall]      = Xstone;
765     lev.android_array[Ystone_sB]        = Xstone;
766     lev.android_array[Ystone_eB]        = Xstone;
767     lev.android_array[Ystone_wB]        = Xstone;
768   }
769
770   if (temp & 8)
771   {
772     lev.android_array[Xbomb]            = Xbomb;
773     lev.android_array[Xbomb_pause]      = Xbomb;
774     lev.android_array[Xbomb_fall]       = Xbomb;
775     lev.android_array[Ybomb_sB]         = Xbomb;
776     lev.android_array[Ybomb_eB]         = Xbomb;
777     lev.android_array[Ybomb_wB]         = Xbomb;
778   }
779
780   if (temp & 16)
781   {
782     lev.android_array[Xnut]             = Xnut;
783     lev.android_array[Xnut_pause]       = Xnut;
784     lev.android_array[Xnut_fall]        = Xnut;
785     lev.android_array[Ynut_sB]          = Xnut;
786     lev.android_array[Ynut_eB]          = Xnut;
787     lev.android_array[Ynut_wB]          = Xnut;
788   }
789
790   if (temp & 32)
791   {
792     lev.android_array[Xtank_n]          = Xtank_n;
793     lev.android_array[Xtank_gon]        = Xtank_n;
794     lev.android_array[Ytank_nB]         = Xtank_n;
795     lev.android_array[Ytank_n_e]        = Xtank_n;
796     lev.android_array[Ytank_n_w]        = Xtank_n;
797
798     lev.android_array[Xtank_e]          = Xtank_e;
799     lev.android_array[Xtank_goe]        = Xtank_e;
800     lev.android_array[Ytank_eB]         = Xtank_e;
801     lev.android_array[Ytank_e_s]        = Xtank_e;
802     lev.android_array[Ytank_e_n]        = Xtank_e;
803
804     lev.android_array[Xtank_s]          = Xtank_s;
805     lev.android_array[Xtank_gos]        = Xtank_s;
806     lev.android_array[Ytank_sB]         = Xtank_s;
807     lev.android_array[Ytank_s_w]        = Xtank_s;
808     lev.android_array[Ytank_s_e]        = Xtank_s;
809
810     lev.android_array[Xtank_w]          = Xtank_w;
811     lev.android_array[Xtank_gow]        = Xtank_w;
812     lev.android_array[Ytank_wB]         = Xtank_w;
813     lev.android_array[Ytank_w_n]        = Xtank_w;
814     lev.android_array[Ytank_w_s]        = Xtank_w;
815   }
816
817   if (temp & 64)
818   {
819     lev.android_array[Xeater_n]         = Xeater_n;
820     lev.android_array[Yeater_nB]        = Xeater_n;
821
822     lev.android_array[Xeater_e]         = Xeater_e;
823     lev.android_array[Yeater_eB]        = Xeater_e;
824
825     lev.android_array[Xeater_s]         = Xeater_s;
826     lev.android_array[Yeater_sB]        = Xeater_s;
827
828     lev.android_array[Xeater_w]         = Xeater_w;
829     lev.android_array[Yeater_wB]        = Xeater_w;
830   }
831
832   if (temp & 128)
833   {
834     lev.android_array[Xbug_n]           = Xbug_gon;
835     lev.android_array[Xbug_gon]         = Xbug_gon;
836     lev.android_array[Ybug_nB]          = Xbug_gon;
837     lev.android_array[Ybug_n_e]         = Xbug_gon;
838     lev.android_array[Ybug_n_w]         = Xbug_gon;
839
840     lev.android_array[Xbug_e]           = Xbug_goe;
841     lev.android_array[Xbug_goe]         = Xbug_goe;
842     lev.android_array[Ybug_eB]          = Xbug_goe;
843     lev.android_array[Ybug_e_s]         = Xbug_goe;
844     lev.android_array[Ybug_e_n]         = Xbug_goe;
845
846     lev.android_array[Xbug_s]           = Xbug_gos;
847     lev.android_array[Xbug_gos]         = Xbug_gos;
848     lev.android_array[Ybug_sB]          = Xbug_gos;
849     lev.android_array[Ybug_s_w]         = Xbug_gos;
850     lev.android_array[Ybug_s_e]         = Xbug_gos;
851
852     lev.android_array[Xbug_w]           = Xbug_gow;
853     lev.android_array[Xbug_gow]         = Xbug_gow;
854     lev.android_array[Ybug_wB]          = Xbug_gow;
855     lev.android_array[Ybug_w_n]         = Xbug_gow;
856     lev.android_array[Ybug_w_s]         = Xbug_gow;
857   }
858
859   if (temp & 256)
860   {
861     lev.android_array[Xalien]           = Xalien;
862     lev.android_array[Xalien_pause]     = Xalien;
863     lev.android_array[Yalien_nB]        = Xalien;
864     lev.android_array[Yalien_eB]        = Xalien;
865     lev.android_array[Yalien_sB]        = Xalien;
866     lev.android_array[Yalien_wB]        = Xalien;
867   }
868
869   if (temp & 512)
870   {
871     lev.android_array[Xspring]          = Xspring;
872     lev.android_array[Xspring_pause]    = Xspring;
873     lev.android_array[Xspring_e]        = Xspring;
874     lev.android_array[Yspring_eB]       = Xspring;
875     lev.android_array[Yspring_kill_eB]  = Xspring;
876     lev.android_array[Xspring_w]        = Xspring;
877     lev.android_array[Yspring_wB]       = Xspring;
878     lev.android_array[Yspring_kill_wB]  = Xspring;
879     lev.android_array[Xspring_fall]     = Xspring;
880     lev.android_array[Yspring_sB]       = Xspring;
881   }
882
883   if (temp & 1024)
884   {
885     lev.android_array[Yballoon_nB]      = Xballoon;
886     lev.android_array[Yballoon_eB]      = Xballoon;
887     lev.android_array[Yballoon_sB]      = Xballoon;
888     lev.android_array[Yballoon_wB]      = Xballoon;
889     lev.android_array[Xballoon]         = Xballoon;
890   }
891
892   if (temp & 2048)
893   {
894     lev.android_array[Xdripper]         = Xdrip_eat;
895     lev.android_array[XdripperB]        = Xdrip_eat;
896     lev.android_array[Xamoeba_1]        = Xdrip_eat;
897     lev.android_array[Xamoeba_2]        = Xdrip_eat;
898     lev.android_array[Xamoeba_3]        = Xdrip_eat;
899     lev.android_array[Xamoeba_4]        = Xdrip_eat;
900     lev.android_array[Xamoeba_5]        = Xdrip_eat;
901     lev.android_array[Xamoeba_6]        = Xdrip_eat;
902     lev.android_array[Xamoeba_7]        = Xdrip_eat;
903     lev.android_array[Xamoeba_8]        = Xdrip_eat;
904   }
905
906   if (temp & 4096)
907   {
908     lev.android_array[Xdynamite]        = Xdynamite;
909   }
910
911   for (temp = 1; temp < 2047; temp++)
912   {
913     switch (src[temp])
914     {
915       case 0x24:                                /* wonderwall */
916         lev.wonderwall_state_initial = 1;
917         lev.wonderwall_time_initial = 9999;
918         break;
919
920       case 0x28:                                /* wheel */
921         lev.wheel_x_initial = temp & 63;
922         lev.wheel_y_initial = temp >> 6;
923         lev.wheel_cnt_initial = lev.wheel_time;
924         break;
925
926 #ifndef BAD_ROLL
927       case 0x63:                                /* spring roll left */
928         src[temp - 1] = 0x45;
929         src[temp] = 0x80;
930         break;
931
932       case 0x64:                                /* spring roll right */
933         src[temp + 1] = 0x45;
934         src[temp] = 0x80;
935         break;
936
937       case 0x72:                                /* nut roll left */
938         src[temp - 1] = 0x25;
939         src[temp] = 0x80;
940         break;
941
942       case 0x73:                                /* nut roll right */
943         src[temp + 1] = 0x25;
944         src[temp] = 0x80;
945         break;
946
947       case 0x77:                                /* bomb roll left */
948         src[temp - 1] = 0x10;
949         src[temp] = 0x80;
950         break;
951
952       case 0x78:                                /* bomb roll right */
953         src[temp + 1] = 0x10;
954         src[temp] = 0x80;
955         break;
956
957       case 0x79:                                /* stone roll left */
958         src[temp - 1] = 0x00;
959         src[temp] = 0x80;
960         break;
961
962       case 0x7A:                                /* stone roll right */
963         src[temp + 1] = 0x00;
964         src[temp] = 0x80;
965         break;
966 #endif
967
968       case 0xA3:                                /* fake blank */
969         lev.lenses_cnt_initial = 9999;
970         break;
971
972       case 0xA4:                                /* fake grass */
973         lev.magnify_cnt_initial = 9999;
974         break;
975     }
976   }
977
978   /* first fill the complete playfield with the default border element */
979   for (y = 0; y < HEIGHT; y++)
980     for (x = 0; x < WIDTH; x++)
981       native_em_level.cave[x][y] = ZBORDER;
982
983   /* then copy the real level contents from level file into the playfield */
984   temp = 0;
985   for (y = 0; y < lev.height; y++)
986     for (x = 0; x < lev.width; x++)
987       native_em_level.cave[x + 1][y + 1] =
988         get_em_element(src[temp++], file_version);
989
990   /* at last, set the two players at their positions in the playfield */
991   /* (native EM[C] levels always have exactly two players in a level) */
992   for (i = 0; i < 2; i++)
993     native_em_level.cave[ply[i].x_initial][ply[i].y_initial] = Zplayer;
994
995   native_em_level.file_version = file_version;
996 }
997
998 void prepare_em_level(void)
999 {
1000   int i, x, y;
1001   int players_left;
1002   boolean team_mode;
1003
1004   /* reset all runtime variables to their initial values */
1005
1006   for (y = 0; y < HEIGHT; y++)
1007     for (x = 0; x < WIDTH; x++)
1008       Cave[y][x] = native_em_level.cave[x][y];
1009
1010   for (y = 0; y < HEIGHT; y++)
1011     for (x = 0; x < WIDTH; x++)
1012       Next[y][x] = Cave[y][x];
1013
1014   for (y = 0; y < HEIGHT; y++)
1015     for (x = 0; x < WIDTH; x++)
1016       Draw[y][x] = Cave[y][x];
1017
1018   lev.time_initial = lev.time_seconds;
1019   lev.time = lev.time_initial;
1020
1021   lev.required = lev.required_initial;
1022   lev.score = 0;
1023
1024   lev.android_move_cnt  = lev.android_move_time;
1025   lev.android_clone_cnt = lev.android_clone_time;
1026
1027   lev.ball_pos = 0;
1028   lev.ball_state = lev.ball_state_initial;
1029   lev.ball_cnt = lev.ball_time;
1030
1031   lev.eater_pos = 0;
1032   lev.shine_cnt = 0;
1033
1034   lev.lenses_cnt = lev.lenses_cnt_initial;
1035   lev.magnify_cnt = lev.magnify_cnt_initial;
1036
1037   lev.wheel_cnt = lev.wheel_cnt_initial;
1038   lev.wheel_x   = lev.wheel_x_initial;
1039   lev.wheel_y   = lev.wheel_y_initial;
1040
1041   lev.wind_direction = lev.wind_direction_initial;
1042   lev.wind_cnt       = lev.wind_cnt_initial;
1043
1044   lev.wonderwall_state = lev.wonderwall_state_initial;
1045   lev.wonderwall_time  = lev.wonderwall_time_initial;
1046
1047   lev.killed_out_of_time = FALSE;
1048
1049   /* determine number of players in this level */
1050   lev.home_initial = 0;
1051
1052   for (i = 0; i < MAX_PLAYERS; i++)
1053   {
1054     ply[i].exists = 0;
1055     ply[i].alive_initial = FALSE;
1056
1057     if (ply[i].x_initial > 0 && ply[i].y_initial > 0)
1058     {
1059       ply[i].exists = 1;
1060
1061       lev.home_initial++;
1062     }
1063   }
1064
1065   team_mode = getTeamMode_EM();
1066
1067   if (!team_mode)
1068     lev.home_initial = 1;
1069
1070   lev.home = lev.home_initial;
1071   players_left = lev.home_initial;
1072
1073   for (i = 0; i < MAX_PLAYERS; i++)
1074   {
1075     if (ply[i].exists)
1076     {
1077       if (players_left)
1078       {
1079         ply[i].alive_initial = TRUE;
1080         players_left--;
1081       }
1082       else
1083       {
1084         int x = ply[i].x_initial;
1085         int y = ply[i].y_initial;
1086
1087         native_em_level.cave[x][y] = Xblank;
1088
1089         Cave[y][x] = Next[y][x] = Draw[y][x] = Xblank;
1090       }
1091     }
1092   }
1093
1094   for (i = 0; i < MAX_PLAYERS; i++)
1095   {
1096     ply[i].num = i;
1097     ply[i].alive = ply[i].alive_initial;
1098     ply[i].dynamite = 0;
1099     ply[i].dynamite_cnt = 0;
1100     ply[i].keys = 0;
1101     ply[i].anim = 0;
1102     ply[i].oldx = ply[i].x = ply[i].x_initial;
1103     ply[i].oldy = ply[i].y = ply[i].y_initial;
1104     ply[i].last_move_dir = MV_NONE;
1105     ply[i].joy_n = ply[i].joy_e = ply[i].joy_s = ply[i].joy_w = 0;
1106     ply[i].joy_snap  = ply[i].joy_drop = 0;
1107     ply[i].joy_stick = ply[i].joy_spin = 0;
1108   }
1109
1110   game_em.any_player_moving = FALSE;
1111   game_em.any_player_snapping = FALSE;
1112
1113   game_em.use_single_button = TRUE;
1114
1115   game_em.last_moving_player = 0;       /* default: first player */
1116
1117   for (i = 0; i < MAX_PLAYERS; i++)
1118     game_em.last_player_direction[i] = MV_NONE;
1119
1120   lev.exit_x = lev.exit_y = -1; /* kludge for playing player exit sound */
1121 }