3 * handle binary emc cave file format
9 /* convert emc caves to intermediate cave format.
11 * the intermediate format supports most emc caves, but some internal
12 * objects are not supported.
15 * - active objects - use global flags instead of individual on/off
16 * - falling or paused objects - become still objects
17 * - sand states - become either sand with/without stone
18 * - collected objects - become a common pause object
19 * - drip states - become a normal drip
22 * - exploding objects (not in emc player either)
24 * pushed objects are supported in the cave, eaters and magic ball.
25 * they behave almost the same as in the emc player, pushing over
26 * steel wall, androids, players etc. a compile time option chooses
27 * if pushed objects go into the acid.
29 * acid is handled completely different in my player. acid top is a
30 * separate object, which can be put anywhere and the beasts will
31 * be gobbled, even if they go in from below. in the emc player, an
32 * acid top without a bottom becomes plant.
34 * borderless caves are supported, almost the same as in the emc
35 * player. going off the left edge of the screen resulted in the
36 * beast/player moving up 1 square (and the player disappeared).
37 * going off the right edge of the screen, the beast/player would
38 * go down 1 square. in my player, everything stays on the same y
39 * coord, which is sensible, but breaks caves which expect the old
43 #define GET_BE16(x) ((&x)[0] << 8 | (&x)[1])
44 #define PUT_BE16(x, y) {(&x)[0] = (y) >> 8; (&x)[1] = (y) & 0xff;}
46 static const short map_emc[256] =
48 Xstone, Xstone, Xdiamond, Xdiamond,
49 Xalien, Xalien, Xblank, Xblank,
50 Xtank_1_n, Xtank_1_e, Xtank_1_s, Xtank_1_w,
51 Xtank_2_n, Xtank_2_e, Xtank_2_s, Xtank_2_w,
53 Xbomb, Xbomb, Xemerald, Xemerald,
54 Xbug_1_n, Xbug_1_e, Xbug_1_s, Xbug_1_w,
55 Xbug_2_n, Xbug_2_e, Xbug_2_s, Xbug_2_w,
56 Xdrip, Xdrip, Xdrip, Xdrip,
58 Xstone, Xbomb, Xdiamond, Xemerald,
59 Xwonderwall, Xnut, Xnut, Xnut,
60 Xwheel, Xeater_n, Xeater_s, Xeater_w,
61 Xeater_e, Xsand_stone, Xblank, Xblank,
63 Xblank, Xsand, Xsand, Xsand,
64 Xsand_stone, Xsand_stone, Xsand_stone, Xsand,
65 Xstone, Xslide_ew, Xslide_ns, Xdynamite_1,
66 Xdynamite_2, Xdynamite_3, Xdynamite_4, Xacid_s,
68 Xexit_1, Xexit_2, Xexit_3, Xballoon,
69 Xplant, Xspring, Xspring_fall, Xspring_w,
70 Xspring_e, Xball_1, Xball_2, Xandroid,
71 Xblank, Xandroid, Xandroid, Xandroid,
73 Xandroid, Xandroid, Xandroid, Xandroid,
74 Xandroid, Xblank, Xblank, Xblank,
75 Xblank, Xblank, Xblank, Xblank,
76 Xblank, Xblank, Xblank, Xblank,
78 Xblank, Xblank, Xblank, Xpush_spring_w,
79 Xpush_spring_e, Xacid_1, Xacid_2, Xacid_3,
80 Xacid_4, Xacid_5, Xacid_6, Xacid_7,
81 Xacid_8, Xblank, Xblank, Xblank,
83 Xblank, Xblank, Xpush_nut_w, Xpush_nut_e,
84 Xsteel_1, Xblank, Xblank, Xpush_bomb_w,
85 Xpush_bomb_e, Xpush_stone_w, Xpush_stone_e, Xblank,
86 Xblank, Xblank, Xblank, Xblank,
88 Xblank, Xroundwall_1, Xgrass, Xsteel_1,
89 Xwall_1, Xkey_1, Xkey_2, Xkey_3,
90 Xkey_4, Xdoor_1, Xdoor_2, Xdoor_3,
91 Xdoor_4, Xfake_amoeba, Xfake_door_1, Xfake_door_2,
93 Xfake_door_3, Xfake_door_4, Xwonderwall, Xwheel,
94 Xsand, Xacid_nw, Xacid_ne, Xacid_sw,
95 Xacid_se, Xfake_blank, Xamoeba_1, Xamoeba_2,
96 Xamoeba_3, Xamoeba_4, Xexit, Xalpha_arrow_w,
98 Xfake_grass, Xlenses, Xmagnify, Xfake_blank,
99 Xfake_grass, Xswitch, Xswitch, Xblank,
100 Xdecor_8, Xdecor_9, Xdecor_10, Xdecor_5,
101 Xalpha_comma, Xalpha_quote, Xalpha_minus, Xdynamite,
103 Xsteel_3, Xdecor_6, Xdecor_7, Xsteel_2,
104 Xroundwall_2, Xdecor_2, Xdecor_4, Xdecor_3,
105 Xwind_any, Xwind_e, Xwind_s, Xwind_w,
106 Xwind_n, Xdirt, Xplant, Xkey_5,
108 Xkey_6, Xkey_7, Xkey_8, Xdoor_5,
109 Xdoor_6, Xdoor_7, Xdoor_8, Xbumper,
110 Xalpha_a, Xalpha_b, Xalpha_c, Xalpha_d,
111 Xalpha_e, Xalpha_f, Xalpha_g, Xalpha_h,
113 Xalpha_i, Xalpha_j, Xalpha_k, Xalpha_l,
114 Xalpha_m, Xalpha_n, Xalpha_o, Xalpha_p,
115 Xalpha_q, Xalpha_r, Xalpha_s, Xalpha_t,
116 Xalpha_u, Xalpha_v, Xalpha_w, Xalpha_x,
118 Xalpha_y, Xalpha_z, Xalpha_0, Xalpha_1,
119 Xalpha_2, Xalpha_3, Xalpha_4, Xalpha_5,
120 Xalpha_6, Xalpha_7, Xalpha_8, Xalpha_9,
121 Xalpha_perio, Xalpha_excla, Xalpha_colon, Xalpha_quest,
123 Xalpha_arrow_e, Xdecor_1, Xfake_door_5, Xfake_door_6,
124 Xfake_door_7, Xfake_door_8, Xblank, Xblank,
125 Xblank, Xblank, Xblank, Xblank,
126 Xblank, Xblank, Xalpha_copyr, Xfake_acid_1
129 static int get_em_element(unsigned short em_element_raw, int file_version)
131 int em_element = map_emc[em_element_raw];
133 if (file_version < FILE_VERSION_EM_V5)
135 /* versions below V5 had no grass, but only sand/dirt */
136 if (em_element == Xgrass)
143 void convert_em_level(unsigned char *src, int file_version)
145 static int eater_offset[8] =
147 2048, 2057, 2066, 2075,
148 2112, 2121, 2130, 2139
152 lev.time_seconds = GET_BE16(src[2110]);
153 if (lev.time_seconds > 9999)
154 lev.time_seconds = 9999;
156 lev.required_initial = src[2095];
158 for (i = 0; i < 2; i++)
160 temp = GET_BE16(src[2096 + i * 2]);
161 ply[i].x_initial = (temp & 63);
162 ply[i].y_initial = (temp >> 6 & 31);
165 temp = GET_BE16(src[2100]) * 28;
168 lev.amoeba_time = temp;
170 lev.android_move_time = GET_BE16(src[2164]);
171 lev.android_clone_time = GET_BE16(src[2166]);
173 lev.ball_random = src[2162] & 1 ? 1 : 0;
174 lev.ball_state_initial = src[2162] & 128 ? 1 : 0;
175 lev.ball_time = GET_BE16(src[2160]);
177 lev.emerald_score = src[2084];
178 lev.diamond_score = src[2085];
179 lev.alien_score = src[2086];
180 lev.tank_score = src[2087];
181 lev.bug_score = src[2088];
182 lev.eater_score = src[2089];
183 lev.nut_score = src[2090];
184 lev.dynamite_score = src[2091];
185 lev.key_score = src[2092];
186 lev.exit_score = src[2093] * 8 / 5;
188 lev.lenses_score = src[2151];
189 lev.magnify_score = src[2152];
190 lev.slurp_score = src[2153];
192 lev.lenses_time = GET_BE16(src[2154]);
193 lev.magnify_time = GET_BE16(src[2156]);
194 lev.wheel_time = GET_BE16(src[2104]);
196 lev.wind_cnt_initial = src[2149] & 15 ? lev.wind_time : 0;
198 lev.wind_direction_initial = (temp & 8 ? 0 :
203 lev.wonderwall_time_initial = GET_BE16(src[2102]);
205 for (i = 0; i < 8; i++)
206 for (x = 0; x < 9; x++)
207 lev.eater_array[i][x] =
208 get_em_element(src[eater_offset[i] + x], file_version);
210 temp = get_em_element(src[2159], file_version);
211 for (y = 0; y < 8; y++)
215 for (x = 0; x < 8; x++)
216 lev.ball_array[y][x] = temp;
220 lev.ball_array[y][1] = (src[2163] & 1) ? temp : Xblank; /* north */
221 lev.ball_array[y][6] = (src[2163] & 2) ? temp : Xblank; /* south */
222 lev.ball_array[y][3] = (src[2163] & 4) ? temp : Xblank; /* west */
223 lev.ball_array[y][4] = (src[2163] & 8) ? temp : Xblank; /* east */
224 lev.ball_array[y][7] = (src[2163] & 16) ? temp : Xblank; /* southeast */
225 lev.ball_array[y][5] = (src[2163] & 32) ? temp : Xblank; /* southwest */
226 lev.ball_array[y][2] = (src[2163] & 64) ? temp : Xblank; /* northeast */
227 lev.ball_array[y][0] = (src[2163] & 128)? temp : Xblank; /* northwest */
231 temp = GET_BE16(src[2168]);
233 lev.android_emerald = (temp & 1) != 0;
234 lev.android_diamond = (temp & 2) != 0;
235 lev.android_stone = (temp & 4) != 0;
236 lev.android_bomb = (temp & 8) != 0;
237 lev.android_nut = (temp & 16) != 0;
238 lev.android_tank = (temp & 32) != 0;
239 lev.android_eater = (temp & 64) != 0;
240 lev.android_bug = (temp & 128) != 0;
241 lev.android_alien = (temp & 256) != 0;
242 lev.android_spring = (temp & 512) != 0;
243 lev.android_balloon = (temp & 1024) != 0;
244 lev.android_amoeba = (temp & 2048) != 0;
245 lev.android_dynamite = (temp & 4096) != 0;
247 for (temp = 1; temp < 2047; temp++)
251 case 36: /* wonderwall */
252 lev.wonderwall_state_initial = 1;
253 lev.wonderwall_time_initial = 9999;
257 lev.wheel_x_initial = temp & 63;
258 lev.wheel_y_initial = temp >> 6;
259 lev.wheel_cnt_initial = lev.wheel_time;
262 case 163: /* fake blank */
263 lev.lenses_cnt_initial = 9999;
266 case 164: /* fake grass */
267 lev.magnify_cnt_initial = 9999;
272 /* first fill the complete playfield with the default border element */
273 for (y = 0; y < CAVE_HEIGHT; y++)
274 for (x = 0; x < CAVE_WIDTH; x++)
275 native_em_level.cave[x][y] = Zborder;
277 /* then copy the real level contents from level file into the playfield */
279 for (y = 0; y < lev.height; y++)
280 for (x = 0; x < lev.width; x++)
281 native_em_level.cave[x][y] =
282 get_em_element(src[temp++], file_version);
284 /* at last, set the two players at their positions in the playfield */
285 /* (native EM[C] levels always have exactly two players in a level) */
286 for (i = 0; i < 2; i++)
287 native_em_level.cave[ply[i].x_initial][ply[i].y_initial] = Zplayer;
289 native_em_level.file_version = file_version;
293 /* convert all emerald mine caves to emc version 6 cave format.
295 * caves are filtered to get rid of invalid or unsupported tiles.
297 * although the result is a somewhat clean cave, it is meant only
298 * to give a common structure for the binary cave format. it is not
299 * for archiving purposes (it is better to keep the raw cave as-is)
300 * and it is not meant for serializing (the intermediate structure
301 * is better defined).
303 * acid top is added to acid bottom in both the cave and the eaters.
304 * fake acid (only in v4) does not exist because it adds nothing to
305 * the game, and is different even in different versions of the emc
308 * v4/v5 time is converted to 10x old time (as it should be).
309 * the reason the kingsoft player used 5x time was copy protection.
311 * note: emc v6 converter has an error in converting v4 eaters to the
312 * wrong bug(24 instead of 20) and tank(12 instead of 8).
315 static const unsigned char map_v6[256] =
319 0,0,2,2, 4,4,118,118, 8,9,10,11, 12,13,14,15,
320 16,16,18,18, 20,21,22,23, 24,25,26,27, 28,28,118,28,
321 0,16,2,18, 36,37,37,37, 40,41,42,43, 44,45,128,128,
322 128,148,148, 148,45,45,45, 148,0,57,58, 59,60,61,62,63,
324 64,65,66,67, 68,69,69,71, 72,73,74,75, 118,75,75,75,
325 75,75,75,75, 75,153,153,153, 153,153,153,153, 153,153,153,153,
326 153,153,153,99, 100,68,68,68, 68,68,68,68, 68,118,118,118,
327 118,118,114,115, 131,118,118,119, 120,121,122,118, 118,118,118,118,
329 128,129,130,131, 132,133,134,135, 136,137,138,139, 140,141,142,143,
330 144,145,146,147, 148,149,150,151, 152,153,154,155, 156,157,158,159,
331 160,161,162,163, 164,165,165,118, 168,169,170,171, 172,173,174,175,
332 176,177,178,179, 180,181,182,183, 184,185,186,187, 188,189,68,191,
334 192,193,194,195, 196,197,198,199, 200,201,202,203, 204,205,206,207,
335 208,209,210,211, 212,213,214,215, 216,217,218,219, 220,221,222,223,
336 224,225,226,227, 228,229,230,231, 232,233,234,235, 236,237,238,239,
337 240,241,242,243, 244,245,153,153, 153,153,153,153, 153,153,153,153
340 static const unsigned char map_v5[256] =
344 0,0,2,2, 4,4,118,118, 8,9,10,11, 12,13,14,15,
345 16,16,18,18, 20,21,22,23, 24,25,26,27, 28,28,118,28,
346 0,16,2,18, 36,37,37,37, 147,41,42,43, 44,45,128,128,
347 128,148,148,148, 45,45,45,148, 0,57,58,59, 60,61,62,63,
349 64,65,66,67, 68,153,153,153, 153,153,153,153, 153,153,153,153,
350 153,153,153,153, 153,153,153,153, 153,153,153,153, 153,153,153,153,
351 153,153,153,153, 153,68,68,68, 68,68,68,68, 68,118,118,118,
352 118,118,114,115, 131,118,118,119, 120,121,122,118, 118,118,118,118,
354 128,129,130,131, 132,133,134,135, 136,137,138,139, 140,141,142,143,
355 144,145,146,147, 148,149,150,151, 152,153,154,155, 156,157,158,159,
356 160,153,153,153, 153,153,153,118, 168,169,170,171, 172,173,174,175,
357 176,177,178,179, 180,181,182,183, 184,185,186,187, 188,189,68,153,
359 153,153,153,153, 153,153,153,153, 200,201,202,203, 204,205,206,207,
360 208,209,210,211, 212,213,214,215, 216,217,218,219, 220,221,222,223,
361 224,225,226,227, 228,229,230,231, 232,233,234,235, 236,237,238,239,
362 240,241,153,153, 153,153,153,153, 153,153,153,153, 153,153,153,153
365 static const unsigned char map_v4[256] =
369 0,0,2,2, 4,4,118,118, 8,9,10,11, 12,13,14,15,
370 16,16,18,18, 20,21,22,23, 24,25,26,27, 28,28,118,28,
371 0,16,2,18, 36,37,37,37, 147,41,42,43, 44,45,128,128,
372 128,148,148,148, 45,45,45,148, 0,153,153,59, 60,61,62,63,
374 64,65,66,153, 153,153,153,153, 153,153,153,153, 153,153,153,153,
375 153,153,153,153, 153,153,153,153, 153,153,153,153, 153,153,153,153,
376 153,153,153,153, 153,153,153,153, 153,153,153,153, 153,153,153,153,
377 153,118,114,115, 131,118,118,119, 120,121,122,118, 118,118,118,118,
379 128,129,130,131, 132,133,134,135, 136,137,138,139, 140,141,142,143,
380 144,145,146,147, 148,149,150,151, 152,68,154,155, 156,157,158,160,
381 160,160,160,160, 160,160,160,160, 160,160,160,160, 160,160,160,175,
382 153,153,153,153, 153,153,153,153, 153,153,153,153, 153,153,68,153,
384 153,153,153,153, 153,153,153,153, 200,201,202,203, 204,205,206,207,
385 208,209,210,211, 212,213,214,215, 216,217,218,219, 220,221,222,223,
386 224,225,226,227, 228,229,230,231, 232,233,234,235, 236,237,238,239,
387 240,241,153,153, 153,153,153,153, 153,153,153,153, 153,153,153,153
390 static const unsigned char map_v4_eater[32] =
392 /* filter for v4 eater */
394 128,18,2,0, 4,8,16,20, 28,37,41,45, 130,129,131,132,
395 133,134,135,136, 146,147,175,65, 66,64,2,18, 128,128,128,128
398 static boolean filename_has_v1_format(char *filename)
400 char *basename = getBaseNamePtr(filename);
402 return (strlen(basename) == 3 &&
403 basename[0] == 'a' &&
404 basename[1] >= 'a' && basename[1] <= 'k' &&
405 basename[2] >= '0' && basename[2] <= '9');
408 int cleanup_em_level(unsigned char *src, int length, char *filename)
410 int file_version = FILE_VERSION_EM_UNKNOWN;
413 if (length >= 2172 &&
414 src[2106] == 255 && /* version id: */
415 src[2107] == 54 && /* '6' */
416 src[2108] == 48 && /* '0' */
417 src[2109] == 48) /* '0' */
419 /* ---------- this cave has V6 file format ---------- */
420 file_version = FILE_VERSION_EM_V6;
422 /* remap elements to internal EMC level format */
423 for (i = 0; i < 2048; i++)
424 src[i] = map_v6[src[i]];
425 for (i = 2048; i < 2084; i++)
426 src[i] = map_v6[src[i]];
427 for (i = 2112; i < 2148; i++)
428 src[i] = map_v6[src[i]];
430 else if (length >= 2110 &&
431 src[2106] == 255 && /* version id: */
432 src[2107] == 53 && /* '5' */
433 src[2108] == 48 && /* '0' */
434 src[2109] == 48) /* '0' */
436 /* ---------- this cave has V5 file format ---------- */
437 file_version = FILE_VERSION_EM_V5;
439 /* remap elements to internal EMC level format */
440 for (i = 0; i < 2048; i++)
441 src[i] = map_v5[src[i]];
442 for (i = 2048; i < 2084; i++)
443 src[i] = map_v5[src[i]];
444 for (i = 2112; i < 2148; i++)
445 src[i] = src[i - 64];
447 else if (length >= 2106 &&
448 (src[1983] == 27 || /* encrypted (only EM I/II/III) */
449 src[1983] == 116 || /* unencrypted (usual case) */
450 src[1983] == 131)) /* unencrypted (rare case) */
452 /* ---------- this cave has V1, V2 or V3 file format ---------- */
454 boolean fix_copyright = FALSE;
457 byte at position 1983 (0x07bf) is used as "magic byte":
458 - 27 (0x1b) => encrypted level (V3 only / Kingsoft original games)
459 - 116 (0x74) => unencrypted level (byte is corrected to 131 (0x83))
460 - 131 (0x83) => unencrypted level (happens only in very rare cases)
463 if (src[1983] == 27) /* (0x1b) -- after decryption: 116 (0x74) */
465 /* this is original (encrypted) Emerald Mine I, II or III level file */
467 int first_byte = src[0];
468 unsigned char code0 = 0x65;
469 unsigned char code1 = 0x11;
471 /* decode encrypted level data */
472 for (i = 0; i < 2106; i++)
477 code0 = (code0 + 7) & 0xff;
480 src[1] = 131; /* needed for all Emerald Mine levels */
482 /* first byte is either 0xf1 (EM I and III) or 0xf5 (EM II) */
483 if (first_byte == 0xf5)
485 src[0] = 131; /* only needed for Emerald Mine II levels */
487 fix_copyright = TRUE;
490 /* ---------- this cave has V3 file format ---------- */
491 file_version = FILE_VERSION_EM_V3;
493 else if (filename_has_v1_format(filename))
495 /* ---------- this cave has V1 file format ---------- */
496 file_version = FILE_VERSION_EM_V1;
500 /* ---------- this cave has V2 file format ---------- */
501 file_version = FILE_VERSION_EM_V2;
504 /* remap elements to internal EMC level format */
505 for (i = 0; i < 2048; i++)
506 src[i] = map_v4[src[i]];
507 for (i = 2048; i < 2084; i++)
508 src[i] = map_v4_eater[src[i] >= 28 ? 0 : src[i]];
509 for (i = 2112; i < 2148; i++)
510 src[i] = src[i - 64];
512 if (fix_copyright) /* fix "(c)" sign in Emerald Mine II levels */
514 for (i = 0; i < 2048; i++)
516 src[i] = 254; /* replace 'Xdecor_1' with 'Xalpha_copyr' */
521 /* ---------- this cave has unknown file format ---------- */
523 /* if file has length of old-style level file, print (wrong) magic byte */
525 Error(ERR_WARN, "unknown magic byte 0x%02x at position 0x%04x",
528 return FILE_VERSION_EM_UNKNOWN;
531 if (file_version < FILE_VERSION_EM_V6)
534 src[2106] = 255; /* version id: */
535 src[2107] = 54; /* '6' */
536 src[2108] = 48; /* '0' */
537 src[2109] = 48; /* '0' */
541 /* stored level time of levels for the V2 player was changed to 50% of the
542 time for the V1 player (original V3 levels already considered this) */
543 if (file_version != FILE_VERSION_EM_V1 &&
544 file_version != FILE_VERSION_EM_V3)
549 for (i = 2148; i < 2172; i++)
556 /* ---------- at this stage, the cave data always has V6 format ---------- */
559 for (i = 0; i < 2048; i++)
562 for (i++; i < 2048; i++)
567 for (i = 64; i < 2048; i++)
568 if (src[i] == 63) /* replace element above 'Xacid_s' ... */
569 src[i - 64] = 101; /* ... with 'Xacid_1' */
571 /* fix acid with no base beneath it (see below for details (*)) */
572 for (i = 64; i < 2048 - 1; i++)
574 if (file_version <= FILE_VERSION_EM_V2 &&
575 src[i - 64] == 101 && src[i] != 63) /* acid without base */
577 if (src[i - 1] == 101 || /* remove acid over acid row */
579 src[i - 64] = 6; /* replace element above with 'Xblank' */
581 src[i - 64] = 255; /* replace element above with 'Xfake_acid_1' */
585 /* fix acid in eater 1 */
586 for (i = 2051; i < 2057; i++)
590 /* fix acid in eater 2 */
591 for (i = 2060; i < 2066; i++)
595 /* fix acid in eater 3 */
596 for (i = 2069; i < 2075; i++)
600 /* fix acid in eater 4 */
601 for (i = 2078; i < 2084; i++)
605 /* fix acid in eater 5 */
606 for (i = 2115; i < 2121; i++)
610 /* fix acid in eater 6 */
611 for (i = 2124; i < 2130; i++)
615 /* fix acid in eater 7 */
616 for (i = 2133; i < 2139; i++)
620 /* fix acid in eater 8 */
621 for (i = 2142; i < 2148; i++)
630 src[GET_BE16(src[2096])] = 128;
634 src[GET_BE16(src[2098])] = 128;
637 if (GET_BE16(src[2100]) > 9999)
638 PUT_BE16(src[2100], 9999);
640 /* time wonderwall */
641 if (GET_BE16(src[2102]) > 9999)
642 PUT_BE16(src[2102], 9999);
645 if (GET_BE16(src[2110]) > 9999)
646 PUT_BE16(src[2110], 9999);
655 if (GET_BE16(src[2154]) > 9999)
656 PUT_BE16(src[2154], 9999);
659 if (GET_BE16(src[2156]) > 9999)
660 PUT_BE16(src[2156], 9999);
664 src[2159] = map_v6[src[2159]];
667 if (GET_BE16(src[2160]) > 9999)
668 PUT_BE16(src[2160], 9999);
675 /* android move pause */
676 if (GET_BE16(src[2164]) > 9999)
677 PUT_BE16(src[2164], 9999);
679 /* android clone pause */
680 if (GET_BE16(src[2166]) > 9999)
681 PUT_BE16(src[2166], 9999);
686 /* size of v6 cave */
690 Error(ERR_DEBUG, "EM level file version: %d", file_version);
699 structure of emerald mine level disk files
700 ----------------------------------------------------------------------
702 if(len >= 2172 && (buf[2106] == 255 && buf[2107] == 54 && buf[2108] == 48 && buf[2109] == 48)) // v6
703 if(len >= 2110 && (buf[2106] == 255 && buf[2107] == 53 && buf[2108] == 48 && buf[2109] == 48)) // v5
704 if(len >= 2106 && (buf[1983] == 116 || buf[2047] == 116)) // v4
705 if(len >= 2106 && (buf[1983] == 27 || buf[2047] == 219)) // v3
707 buf[0]=241;buf[1]=248;for(i=0,j=101;i<2106;i++,j+=7)buf[i]=(buf[i]^j)-17; // decrypt
709 number of movements (calls to logic) = time * 50 / 8
711 {} reserved (but some broken levels use them)
713 ----------------------------------------------------------------------
733 2095: emeralds needed
737 2102: wonderwall time
739 2106: ID (0xff363030)
745 2148: flags bit#7=NOI #6=RIS
746 2149: wind direction bit#0=right #1=down #2=left #3=up
747 2150: cave number bit#7=teamwork
756 2162: ball info bit#15=switch state #8=random
757 ; bit#0=N #1=S #2=W #3=E #4=SE #5=SW #6=NE #7=NW
758 2164: android move speed
759 2166: android clone speed
761 ; bit#0=emerald #1=diamond #2=stone #3=bomb #4=nut #5=tank #6=eater
762 ; #7=bug #8=alien #9=spring #10=balloon #11=ameuba #12=dynamite
767 1: stone {stone_fall}
769 3: diamond {diamond_fall}
771 5: alien {alien_pause}
785 19: emerald {emerald_fall}
796 30: blank {drip_stretchB}
797 31: drip {drip_stretch}
798 32: stone {stone_pause}
799 33: bomb {bomb_pause}
800 34: diamond {diamond_pause}
801 35: emerald {emerald_pause}
802 36: wonderwall {wonderwallB}
812 46: blank {sand_stonein_2}
813 47: blank {sand_stonein_3}
814 48: blank {sand_stonein_4}
815 49: sand {sand_stonesand_2}
816 50: sand {sand_stonesand_3}
817 51: sand {sand_stonesand_4}
818 52: sand_stone {sand_sandstone_2}
819 53: sand_stone {sand_sandstone_3}
820 54: sand_stone {sand_sandstone_4}
821 55: sand {sand_stonesand_4}
822 56: stone {sand_stoneout_2}
836 70: spring {spring_fall}
837 71: spring {spring_w}
838 72: spring {spring_e}
843 77: android {android_n_1}
844 78: android {android_n_2}
845 79: android {android_s_1}
846 80: android {android_s_2}
847 81: android {android_e_1}
848 82: android {android_e_2}
849 83: android {android_w_1}
850 84: android {android_w_2}
865 99: spring {push_spring_w}
866 100: spring {push_spring_e}
875 109: pause {grass_wB}
876 110: pause {grass_eB}
877 111: pause {grass_nB}
878 112: pause {grass_sB}
879 113: pause {dynamite_blank}
880 114: nut {push_nut_w}
881 115: nut {push_nut_e}
882 116: steel_2 {end of level}
884 118: pause {emerald_blank}
885 119: bomb {push_bomb_w}
886 120: bomb {push_bomb_e}
887 121: stone {push_stone_w}
888 122: stone {push_stone_e}
889 123: pause {diamond_blank}
930 163: fake_blank {fake_blankB}
931 164: fake_grass {fake_grassB}
933 166: switch {switchB}
1024 ----------------------------------------------------------------------
1040 2091: dynamite value
1044 2095: emeralds needed
1048 2102: wonderwall time
1050 2106: ID (0xff353030)
1054 1: stone {stone_fall}
1056 3: diamond {diamond_fall}
1058 5: alien {alien_pause}
1070 17: bomb {bomb_fall}
1072 19: emerald {emerald_fall}
1082 29: drip {drip_fall}
1083 30: blank {drip_stretchB}
1084 31: drip {drip_stretch}
1085 32: stone {stone_pause}
1086 33: bomb {bomb_pause}
1087 34: diamond {diamond_pause}
1088 35: emerald {emerald_pause}
1089 36: wonderwall {wonderwallB}
1099 46: blank {sand_stonein_2}
1100 47: blank {sand_stonein_3}
1101 48: blank {sand_stonein_4}
1102 49: sand {sand_stonesand_2}
1103 50: sand {sand_stonesand_3}
1104 51: sand {sand_stonesand_4}
1105 52: sand_stone {sand_sandstone_2}
1106 53: sand_stone {sand_sandstone_3}
1107 54: sand_stone {sand_sandstone_4}
1108 55: sand {sand_stonesand_4}
1109 56: stone {sand_stoneout_2}
1162 109: pause {grass_wB}
1163 110: pause {grass_eB}
1164 111: pause {grass_nB}
1165 112: pause {grass_sB}
1166 113: pause {dynamite_blank}
1167 114: nut {push_nut_w}
1168 115: nut {push_nut_e}
1169 116: steel_2 {end of level}
1170 117: dynamite_4 {boom_2}
1171 118: pause {emerald_blank}
1172 119: bomb {push_bomb_w}
1173 120: bomb {push_bomb_e}
1174 121: stone {push_stone_w}
1175 122: stone {push_stone_e}
1176 123: pause {diamond_blank}
1177 124: pause {dirt_wB}
1178 125: pause {dirt_eB}
1179 126: pause {dirt_nB}
1180 127: pause {dirt_sB}
1311 ----------------------------------------------------------------------
1327 2091: dynamite value
1331 2095: emeralds needed
1335 2102: wonderwall time
1365 26: diamond {diamond_shine}
1366 27: emerald {emerald_shine}
1369 1: stone {stone_fall}
1371 3: diamond {diamond_fall}
1373 5: alien {alien_pause}
1385 17: bomb {bomb_fall}
1387 19: emerald {emerald_fall}
1397 29: drip {drip_fall}
1398 30: blank {drip_stretchB}
1399 31: drip {drip_stretch}
1400 32: stone {stone_pause}
1401 33: bomb {bomb_pause}
1402 34: diamond {diamond_pause}
1403 35: emerald {emerald_pause}
1404 36: wonderwall {wonderwallB}
1414 46: blank {sand_stonein_2}
1415 47: blank {sand_stonein_3}
1416 48: blank {sand_stonein_4}
1417 49: sand {sand_stonesand_2}
1418 50: sand {sand_stonesand_3}
1419 51: sand {sand_stonesand_4}
1420 52: sand_stone {sand_sandstone_2}
1421 53: sand_stone {sand_sandstone_3}
1422 54: sand_stone {sand_sandstone_4}
1423 55: sand {sand_stonesand_4}
1424 56: stone {sand_stoneout_2}
1481 113: pause {dynamite_blank}
1482 114: nut {push_nut_w}
1483 115: nut {push_nut_e}
1484 116: steel_1 {end of level}
1485 117: dynamite_4 {boom_2}
1486 118: pause {emerald_blank}
1487 119: bomb {push_bomb_w}
1488 120: bomb {push_bomb_e}
1489 121: stone {push_stone_w}
1490 122: stone {push_stone_e}
1491 123: pause {diamond_blank}
1492 124: pause {dirt_wB}
1493 125: pause {dirt_eB}
1494 126: pause {dirt_nB}
1495 127: pause {dirt_sB}
1528 159: fake_grass {dirt}
1529 160: fake_grass {dirt}
1530 161: fake_grass {dirt}
1531 162: fake_grass {dirt}
1532 163: fake_grass {dirt}
1533 164: fake_grass {dirt}
1534 165: fake_grass {dirt}
1535 166: fake_grass {dirt}
1536 167: fake_grass {dirt}
1537 168: fake_grass {dirt}
1538 169: fake_grass {dirt}
1539 170: fake_grass {dirt}
1540 171: fake_grass {dirt}
1541 172: fake_grass {dirt}
1542 173: fake_grass {dirt}
1543 174: fake_grass {dirt}
1609 240: alpha_arrow_e {}
1610 241: decor_1 {alpha_copyr}
1626 ----------------------------------------------------------------------