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