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 static const short map_emc[256] =
45 Xstone, Xstone, Xdiamond, Xdiamond,
46 Xalien, Xalien, Xblank, Xblank,
47 Xtank_1_n, Xtank_1_e, Xtank_1_s, Xtank_1_w,
48 Xtank_2_n, Xtank_2_e, Xtank_2_s, Xtank_2_w,
50 Xbomb, Xbomb, Xemerald, Xemerald,
51 Xbug_1_n, Xbug_1_e, Xbug_1_s, Xbug_1_w,
52 Xbug_2_n, Xbug_2_e, Xbug_2_s, Xbug_2_w,
53 Xdrip, Xdrip, Xdrip, Xdrip,
55 Xstone, Xbomb, Xdiamond, Xemerald,
56 Xwonderwall, Xnut, Xnut, Xnut,
57 Xwheel, Xeater_n, Xeater_s, Xeater_w,
58 Xeater_e, Xsand_stone, Xblank, Xblank,
60 Xblank, Xsand, Xsand, Xsand,
61 Xsand_stone, Xsand_stone, Xsand_stone, Xsand,
62 Xstone, Xslide_ew, Xslide_ns, Xdynamite_1,
63 Xdynamite_2, Xdynamite_3, Xdynamite_4, Xacid_s,
65 Xexit_1, Xexit_2, Xexit_3, Xballoon,
66 Xplant, Xspring, Xspring_fall, Xspring_w,
67 Xspring_e, Xball_1, Xball_2, Xandroid,
68 Xblank, Xandroid, Xandroid, Xandroid,
70 Xandroid, Xandroid, Xandroid, Xandroid,
71 Xandroid, Xblank, Xblank, Xblank,
72 Xblank, Xblank, Xblank, Xblank,
73 Xblank, Xblank, Xblank, Xblank,
75 Xblank, Xblank, Xblank, Xpush_spring_w,
76 Xpush_spring_e, Xacid_1, Xacid_2, Xacid_3,
77 Xacid_4, Xacid_5, Xacid_6, Xacid_7,
78 Xacid_8, Xblank, Xblank, Xblank,
80 Xblank, Xblank, Xpush_nut_w, Xpush_nut_e,
81 Xsteel_1, Xblank, Xblank, Xpush_bomb_w,
82 Xpush_bomb_e, Xpush_stone_w, Xpush_stone_e, Xblank,
83 Xblank, Xblank, Xblank, Xblank,
85 Xblank, Xroundwall_1, Xgrass, Xsteel_1,
86 Xwall_1, Xkey_1, Xkey_2, Xkey_3,
87 Xkey_4, Xdoor_1, Xdoor_2, Xdoor_3,
88 Xdoor_4, Xfake_amoeba, Xfake_door_1, Xfake_door_2,
90 Xfake_door_3, Xfake_door_4, Xwonderwall, Xwheel,
91 Xsand, Xacid_nw, Xacid_ne, Xacid_sw,
92 Xacid_se, Xfake_blank, Xamoeba_1, Xamoeba_2,
93 Xamoeba_3, Xamoeba_4, Xexit, Xalpha_arrow_w,
95 Xfake_grass, Xlenses, Xmagnify, Xfake_blank,
96 Xfake_grass, Xswitch, Xswitch, Xblank,
97 Xdecor_8, Xdecor_9, Xdecor_10, Xdecor_5,
98 Xalpha_comma, Xalpha_quote, Xalpha_minus, Xdynamite,
100 Xsteel_3, Xdecor_6, Xdecor_7, Xsteel_2,
101 Xroundwall_2, Xdecor_2, Xdecor_4, Xdecor_3,
102 Xwind_any, Xwind_e, Xwind_s, Xwind_w,
103 Xwind_n, Xdirt, Xplant, Xkey_5,
105 Xkey_6, Xkey_7, Xkey_8, Xdoor_5,
106 Xdoor_6, Xdoor_7, Xdoor_8, Xbumper,
107 Xalpha_a, Xalpha_b, Xalpha_c, Xalpha_d,
108 Xalpha_e, Xalpha_f, Xalpha_g, Xalpha_h,
110 Xalpha_i, Xalpha_j, Xalpha_k, Xalpha_l,
111 Xalpha_m, Xalpha_n, Xalpha_o, Xalpha_p,
112 Xalpha_q, Xalpha_r, Xalpha_s, Xalpha_t,
113 Xalpha_u, Xalpha_v, Xalpha_w, Xalpha_x,
115 Xalpha_y, Xalpha_z, Xalpha_0, Xalpha_1,
116 Xalpha_2, Xalpha_3, Xalpha_4, Xalpha_5,
117 Xalpha_6, Xalpha_7, Xalpha_8, Xalpha_9,
118 Xalpha_perio, Xalpha_excla, Xalpha_colon, Xalpha_quest,
120 Xalpha_arrow_e, Xdecor_1, Xfake_door_5, Xfake_door_6,
121 Xfake_door_7, Xfake_door_8, Xblank, Xblank,
122 Xblank, Xblank, Xblank, Xblank,
123 Xblank, Xblank, Xalpha_copyr, Xfake_acid_1
126 static int get_em_element(unsigned short em_element_raw, int file_version)
128 int em_element = map_emc[em_element_raw];
130 if (file_version < FILE_VERSION_EM_V5)
132 /* versions below V5 had no grass, but only sand/dirt */
133 if (em_element == Xgrass)
140 void convert_em_level(unsigned char *src, int file_version)
142 static int eater_offset[8] =
144 0x800, 0x809, 0x812, 0x81B, 0x840, 0x849, 0x852, 0x85B
148 lev.time_seconds = src[0x83E] << 8 | src[0x83F];
149 if (lev.time_seconds > 9999)
150 lev.time_seconds = 9999;
152 lev.required_initial = src[0x82F];
154 for (i = 0; i < 2; i++)
156 temp = src[0x830 + i * 2] << 8 | src[0x831 + i * 2];
157 ply[i].x_initial = (temp & 63);
158 ply[i].y_initial = (temp >> 6 & 31);
161 temp = (src[0x834] << 8 | src[0x835]) * 28;
164 lev.amoeba_time = temp;
166 lev.android_move_time = src[0x874] << 8 | src[0x875];
167 lev.android_clone_time = src[0x876] << 8 | src[0x877];
169 lev.ball_random = src[0x872] & 1 ? 1 : 0;
170 lev.ball_state_initial = src[0x872] & 128 ? 1 : 0;
171 lev.ball_time = src[0x870] << 8 | src[0x871];
173 lev.emerald_score = src[0x824];
174 lev.diamond_score = src[0x825];
175 lev.alien_score = src[0x826];
176 lev.tank_score = src[0x827];
177 lev.bug_score = src[0x828];
178 lev.eater_score = src[0x829];
179 lev.nut_score = src[0x82A];
180 lev.dynamite_score = src[0x82B];
181 lev.key_score = src[0x82C];
182 lev.exit_score = src[0x82D] * 8 / 5;
183 lev.lenses_score = src[0x867];
184 lev.magnify_score = src[0x868];
185 lev.slurp_score = src[0x869];
187 lev.lenses_time = src[0x86A] << 8 | src[0x86B];
188 lev.magnify_time = src[0x86C] << 8 | src[0x86D];
189 lev.wheel_time = src[0x838] << 8 | src[0x839];
191 lev.wind_cnt_initial = src[0x865] & 15 ? lev.wind_time : 0;
193 lev.wind_direction_initial = (temp & 8 ? 0 :
198 lev.wonderwall_time_initial = src[0x836] << 8 | src[0x837];
200 for (i = 0; i < 8; i++)
201 for (x = 0; x < 9; x++)
202 lev.eater_array[i][x] =
203 get_em_element(src[eater_offset[i] + x], file_version);
205 temp = get_em_element(src[0x86F], file_version);
206 for (y = 0; y < 8; y++)
210 for (x = 0; x < 8; x++)
211 lev.ball_array[y][x] = temp;
215 lev.ball_array[y][1] = (src[0x873] & 1) ? temp : Xblank; /* north */
216 lev.ball_array[y][6] = (src[0x873] & 2) ? temp : Xblank; /* south */
217 lev.ball_array[y][3] = (src[0x873] & 4) ? temp : Xblank; /* west */
218 lev.ball_array[y][4] = (src[0x873] & 8) ? temp : Xblank; /* east */
219 lev.ball_array[y][7] = (src[0x873] & 16) ? temp : Xblank; /* southeast */
220 lev.ball_array[y][5] = (src[0x873] & 32) ? temp : Xblank; /* southwest */
221 lev.ball_array[y][2] = (src[0x873] & 64) ? temp : Xblank; /* northeast */
222 lev.ball_array[y][0] = (src[0x873] & 128)? temp : Xblank; /* northwest */
226 temp = src[0x878] << 8 | src[0x879];
230 lev.android_array[Xemerald] = Xemerald;
231 lev.android_array[Xemerald_pause] = Xemerald;
232 lev.android_array[Xemerald_fall] = Xemerald;
233 lev.android_array[Yemerald_sB] = Xemerald;
234 lev.android_array[Yemerald_eB] = Xemerald;
235 lev.android_array[Yemerald_wB] = Xemerald;
240 lev.android_array[Xdiamond] = Xdiamond;
241 lev.android_array[Xdiamond_pause] = Xdiamond;
242 lev.android_array[Xdiamond_fall] = Xdiamond;
243 lev.android_array[Ydiamond_sB] = Xdiamond;
244 lev.android_array[Ydiamond_eB] = Xdiamond;
245 lev.android_array[Ydiamond_wB] = Xdiamond;
250 lev.android_array[Xstone] = Xstone;
251 lev.android_array[Xstone_pause] = Xstone;
252 lev.android_array[Xstone_fall] = Xstone;
253 lev.android_array[Ystone_sB] = Xstone;
254 lev.android_array[Ystone_eB] = Xstone;
255 lev.android_array[Ystone_wB] = Xstone;
260 lev.android_array[Xbomb] = Xbomb;
261 lev.android_array[Xbomb_pause] = Xbomb;
262 lev.android_array[Xbomb_fall] = Xbomb;
263 lev.android_array[Ybomb_sB] = Xbomb;
264 lev.android_array[Ybomb_eB] = Xbomb;
265 lev.android_array[Ybomb_wB] = Xbomb;
270 lev.android_array[Xnut] = Xnut;
271 lev.android_array[Xnut_pause] = Xnut;
272 lev.android_array[Xnut_fall] = Xnut;
273 lev.android_array[Ynut_sB] = Xnut;
274 lev.android_array[Ynut_eB] = Xnut;
275 lev.android_array[Ynut_wB] = Xnut;
280 lev.android_array[Xtank_1_n] = Xtank_1_n;
281 lev.android_array[Xtank_2_n] = Xtank_1_n;
282 lev.android_array[Ytank_nB] = Xtank_1_n;
283 lev.android_array[Ytank_n_e] = Xtank_1_n;
284 lev.android_array[Ytank_n_w] = Xtank_1_n;
286 lev.android_array[Xtank_1_e] = Xtank_1_e;
287 lev.android_array[Xtank_2_e] = Xtank_1_e;
288 lev.android_array[Ytank_eB] = Xtank_1_e;
289 lev.android_array[Ytank_e_s] = Xtank_1_e;
290 lev.android_array[Ytank_e_n] = Xtank_1_e;
292 lev.android_array[Xtank_1_s] = Xtank_1_s;
293 lev.android_array[Xtank_2_s] = Xtank_1_s;
294 lev.android_array[Ytank_sB] = Xtank_1_s;
295 lev.android_array[Ytank_s_w] = Xtank_1_s;
296 lev.android_array[Ytank_s_e] = Xtank_1_s;
298 lev.android_array[Xtank_1_w] = Xtank_1_w;
299 lev.android_array[Xtank_2_w] = Xtank_1_w;
300 lev.android_array[Ytank_wB] = Xtank_1_w;
301 lev.android_array[Ytank_w_n] = Xtank_1_w;
302 lev.android_array[Ytank_w_s] = Xtank_1_w;
307 lev.android_array[Xeater_n] = Xeater_n;
308 lev.android_array[Yeater_nB] = Xeater_n;
310 lev.android_array[Xeater_e] = Xeater_e;
311 lev.android_array[Yeater_eB] = Xeater_e;
313 lev.android_array[Xeater_s] = Xeater_s;
314 lev.android_array[Yeater_sB] = Xeater_s;
316 lev.android_array[Xeater_w] = Xeater_w;
317 lev.android_array[Yeater_wB] = Xeater_w;
322 lev.android_array[Xbug_1_n] = Xbug_2_n;
323 lev.android_array[Xbug_2_n] = Xbug_2_n;
324 lev.android_array[Ybug_nB] = Xbug_2_n;
325 lev.android_array[Ybug_n_e] = Xbug_2_n;
326 lev.android_array[Ybug_n_w] = Xbug_2_n;
328 lev.android_array[Xbug_1_e] = Xbug_2_e;
329 lev.android_array[Xbug_2_e] = Xbug_2_e;
330 lev.android_array[Ybug_eB] = Xbug_2_e;
331 lev.android_array[Ybug_e_s] = Xbug_2_e;
332 lev.android_array[Ybug_e_n] = Xbug_2_e;
334 lev.android_array[Xbug_1_s] = Xbug_2_s;
335 lev.android_array[Xbug_2_s] = Xbug_2_s;
336 lev.android_array[Ybug_sB] = Xbug_2_s;
337 lev.android_array[Ybug_s_w] = Xbug_2_s;
338 lev.android_array[Ybug_s_e] = Xbug_2_s;
340 lev.android_array[Xbug_1_w] = Xbug_2_w;
341 lev.android_array[Xbug_2_w] = Xbug_2_w;
342 lev.android_array[Ybug_wB] = Xbug_2_w;
343 lev.android_array[Ybug_w_n] = Xbug_2_w;
344 lev.android_array[Ybug_w_s] = Xbug_2_w;
349 lev.android_array[Xalien] = Xalien;
350 lev.android_array[Xalien_pause] = Xalien;
351 lev.android_array[Yalien_nB] = Xalien;
352 lev.android_array[Yalien_eB] = Xalien;
353 lev.android_array[Yalien_sB] = Xalien;
354 lev.android_array[Yalien_wB] = Xalien;
359 lev.android_array[Xspring] = Xspring;
360 lev.android_array[Xspring_pause] = Xspring;
361 lev.android_array[Xspring_e] = Xspring;
362 lev.android_array[Yspring_eB] = Xspring;
363 lev.android_array[Yspring_alien_eB] = Xspring;
364 lev.android_array[Xspring_w] = Xspring;
365 lev.android_array[Yspring_wB] = Xspring;
366 lev.android_array[Yspring_alien_wB] = Xspring;
367 lev.android_array[Xspring_fall] = Xspring;
368 lev.android_array[Yspring_sB] = Xspring;
373 lev.android_array[Yballoon_nB] = Xballoon;
374 lev.android_array[Yballoon_eB] = Xballoon;
375 lev.android_array[Yballoon_sB] = Xballoon;
376 lev.android_array[Yballoon_wB] = Xballoon;
377 lev.android_array[Xballoon] = Xballoon;
382 lev.android_array[Xfake_amoeba] = Xdrip;
383 lev.android_array[Yfake_amoeba] = Xdrip;
384 lev.android_array[Xamoeba_1] = Xdrip;
385 lev.android_array[Xamoeba_2] = Xdrip;
386 lev.android_array[Xamoeba_3] = Xdrip;
387 lev.android_array[Xamoeba_4] = Xdrip;
388 lev.android_array[Xamoeba_5] = Xdrip;
389 lev.android_array[Xamoeba_6] = Xdrip;
390 lev.android_array[Xamoeba_7] = Xdrip;
391 lev.android_array[Xamoeba_8] = Xdrip;
396 lev.android_array[Xdynamite] = Xdynamite;
399 for (temp = 1; temp < 2047; temp++)
403 case 0x24: /* wonderwall */
404 lev.wonderwall_state_initial = 1;
405 lev.wonderwall_time_initial = 9999;
408 case 0x28: /* wheel */
409 lev.wheel_x_initial = temp & 63;
410 lev.wheel_y_initial = temp >> 6;
411 lev.wheel_cnt_initial = lev.wheel_time;
414 case 0xA3: /* fake blank */
415 lev.lenses_cnt_initial = 9999;
418 case 0xA4: /* fake grass */
419 lev.magnify_cnt_initial = 9999;
424 /* first fill the complete playfield with the default border element */
425 for (y = 0; y < CAVE_HEIGHT; y++)
426 for (x = 0; x < CAVE_WIDTH; x++)
427 native_em_level.cave[x][y] = Zborder;
429 /* then copy the real level contents from level file into the playfield */
431 for (y = 0; y < lev.height; y++)
432 for (x = 0; x < lev.width; x++)
433 native_em_level.cave[x][y] =
434 get_em_element(src[temp++], file_version);
436 /* at last, set the two players at their positions in the playfield */
437 /* (native EM[C] levels always have exactly two players in a level) */
438 for (i = 0; i < 2; i++)
439 native_em_level.cave[ply[i].x_initial][ply[i].y_initial] = Zplayer;
441 native_em_level.file_version = file_version;
445 /* convert all emerald mine caves to emc version 6 cave format.
447 * caves are filtered to get rid of invalid or unsupported tiles.
449 * although the result is a somewhat clean cave, it is meant only
450 * to give a common structure for the binary cave format. it is not
451 * for archiving purposes (it is better to keep the raw cave as-is)
452 * and it is not meant for serializing (the intermediate structure
453 * is better defined).
455 * acid top is added to acid bottom in both the cave and the eaters.
456 * fake acid (only in v4) does not exist because it adds nothing to
457 * the game, and is different even in different versions of the emc
460 * v4/v5 time is converted to 10x old time (as it should be).
461 * the reason the kingsoft player used 5x time was copy protection.
463 * note: emc v6 converter has an error in converting v4 eaters to the
464 * wrong bug(24 instead of 20) and tank(12 instead of 8).
467 static const unsigned char map_v6[256] =
471 0,0,2,2, 4,4,118,118, 8,9,10,11, 12,13,14,15,
472 16,16,18,18, 20,21,22,23, 24,25,26,27, 28,28,118,28,
473 0,16,2,18, 36,37,37,37, 40,41,42,43, 44,45,128,128,
474 128,148,148, 148,45,45,45, 148,0,57,58, 59,60,61,62,63,
476 64,65,66,67, 68,69,69,71, 72,73,74,75, 118,75,75,75,
477 75,75,75,75, 75,153,153,153, 153,153,153,153, 153,153,153,153,
478 153,153,153,99, 100,68,68,68, 68,68,68,68, 68,118,118,118,
479 118,118,114,115, 131,118,118,119, 120,121,122,118, 118,118,118,118,
481 128,129,130,131, 132,133,134,135, 136,137,138,139, 140,141,142,143,
482 144,145,146,147, 148,149,150,151, 152,153,154,155, 156,157,158,159,
483 160,161,162,163, 164,165,165,118, 168,169,170,171, 172,173,174,175,
484 176,177,178,179, 180,181,182,183, 184,185,186,187, 188,189,68,191,
486 192,193,194,195, 196,197,198,199, 200,201,202,203, 204,205,206,207,
487 208,209,210,211, 212,213,214,215, 216,217,218,219, 220,221,222,223,
488 224,225,226,227, 228,229,230,231, 232,233,234,235, 236,237,238,239,
489 240,241,242,243, 244,245,153,153, 153,153,153,153, 153,153,153,153
492 static const unsigned char map_v5[256] =
496 0,0,2,2, 4,4,118,118, 8,9,10,11, 12,13,14,15,
497 16,16,18,18, 20,21,22,23, 24,25,26,27, 28,28,118,28,
498 0,16,2,18, 36,37,37,37, 147,41,42,43, 44,45,128,128,
499 128,148,148,148, 45,45,45,148, 0,57,58,59, 60,61,62,63,
501 64,65,66,67, 68,153,153,153, 153,153,153,153, 153,153,153,153,
502 153,153,153,153, 153,153,153,153, 153,153,153,153, 153,153,153,153,
503 153,153,153,153, 153,68,68,68, 68,68,68,68, 68,118,118,118,
504 118,118,114,115, 131,118,118,119, 120,121,122,118, 118,118,118,118,
506 128,129,130,131, 132,133,134,135, 136,137,138,139, 140,141,142,143,
507 144,145,146,147, 148,149,150,151, 152,153,154,155, 156,157,158,159,
508 160,153,153,153, 153,153,153,118, 168,169,170,171, 172,173,174,175,
509 176,177,178,179, 180,181,182,183, 184,185,186,187, 188,189,68,153,
511 153,153,153,153, 153,153,153,153, 200,201,202,203, 204,205,206,207,
512 208,209,210,211, 212,213,214,215, 216,217,218,219, 220,221,222,223,
513 224,225,226,227, 228,229,230,231, 232,233,234,235, 236,237,238,239,
514 240,241,153,153, 153,153,153,153, 153,153,153,153, 153,153,153,153
517 static const unsigned char map_v4[256] =
521 0,0,2,2, 4,4,118,118, 8,9,10,11, 12,13,14,15,
522 16,16,18,18, 20,21,22,23, 24,25,26,27, 28,28,118,28,
523 0,16,2,18, 36,37,37,37, 147,41,42,43, 44,45,128,128,
524 128,148,148,148, 45,45,45,148, 0,153,153,59, 60,61,62,63,
526 64,65,66,153, 153,153,153,153, 153,153,153,153, 153,153,153,153,
527 153,153,153,153, 153,153,153,153, 153,153,153,153, 153,153,153,153,
528 153,153,153,153, 153,153,153,153, 153,153,153,153, 153,153,153,153,
529 153,118,114,115, 131,118,118,119, 120,121,122,118, 118,118,118,118,
531 128,129,130,131, 132,133,134,135, 136,137,138,139, 140,141,142,143,
532 144,145,146,147, 148,149,150,151, 152,68,154,155, 156,157,158,160,
533 160,160,160,160, 160,160,160,160, 160,160,160,160, 160,160,160,175,
534 153,153,153,153, 153,153,153,153, 153,153,153,153, 153,153,68,153,
536 153,153,153,153, 153,153,153,153, 200,201,202,203, 204,205,206,207,
537 208,209,210,211, 212,213,214,215, 216,217,218,219, 220,221,222,223,
538 224,225,226,227, 228,229,230,231, 232,233,234,235, 236,237,238,239,
539 240,241,153,153, 153,153,153,153, 153,153,153,153, 153,153,153,153
542 static const unsigned char map_v4_eater[32] =
544 /* filter for v4 eater */
546 128,18,2,0, 4,8,16,20, 28,37,41,45, 130,129,131,132,
547 133,134,135,136, 146,147,175,65, 66,64,2,18, 128,128,128,128
550 static boolean filename_has_v1_format(char *filename)
552 char *basename = getBaseNamePtr(filename);
554 return (strlen(basename) == 3 &&
555 basename[0] == 'a' &&
556 basename[1] >= 'a' && basename[1] <= 'k' &&
557 basename[2] >= '0' && basename[2] <= '9');
560 int cleanup_em_level(unsigned char *src, int length, char *filename)
562 int file_version = FILE_VERSION_EM_UNKNOWN;
565 if (length >= 2172 &&
566 src[2106] == 255 && /* version id: */
567 src[2107] == 54 && /* '6' */
568 src[2108] == 48 && /* '0' */
569 src[2109] == 48) /* '0' */
571 /* ---------- this cave has V6 file format ---------- */
572 file_version = FILE_VERSION_EM_V6;
574 /* remap elements to internal EMC level format */
575 for (i = 0; i < 2048; i++)
576 src[i] = map_v6[src[i]];
577 for (i = 2048; i < 2084; i++)
578 src[i] = map_v6[src[i]];
579 for (i = 2112; i < 2148; i++)
580 src[i] = map_v6[src[i]];
582 else if (length >= 2110 &&
583 src[2106] == 255 && /* version id: */
584 src[2107] == 53 && /* '5' */
585 src[2108] == 48 && /* '0' */
586 src[2109] == 48) /* '0' */
588 /* ---------- this cave has V5 file format ---------- */
589 file_version = FILE_VERSION_EM_V5;
591 /* remap elements to internal EMC level format */
592 for (i = 0; i < 2048; i++)
593 src[i] = map_v5[src[i]];
594 for (i = 2048; i < 2084; i++)
595 src[i] = map_v5[src[i]];
596 for (i = 2112; i < 2148; i++)
597 src[i] = src[i - 64];
599 else if (length >= 2106 &&
600 (src[1983] == 27 || /* encrypted (only EM I/II/III) */
601 src[1983] == 116 || /* unencrypted (usual case) */
602 src[1983] == 131)) /* unencrypted (rare case) */
604 /* ---------- this cave has V1, V2 or V3 file format ---------- */
606 boolean fix_copyright = FALSE;
609 byte at position 1983 (0x07bf) is used as "magic byte":
610 - 27 (0x1b) => encrypted level (V3 only / Kingsoft original games)
611 - 116 (0x74) => unencrypted level (byte is corrected to 131 (0x83))
612 - 131 (0x83) => unencrypted level (happens only in very rare cases)
615 if (src[1983] == 27) /* (0x1b) -- after decryption: 116 (0x74) */
617 /* this is original (encrypted) Emerald Mine I, II or III level file */
619 int first_byte = src[0];
620 unsigned char code0 = 0x65;
621 unsigned char code1 = 0x11;
623 /* decode encrypted level data */
624 for (i = 0; i < 2106; i++)
629 code0 = (code0 + 7) & 0xff;
632 src[1] = 131; /* needed for all Emerald Mine levels */
634 /* first byte is either 0xf1 (EM I and III) or 0xf5 (EM II) */
635 if (first_byte == 0xf5)
637 src[0] = 131; /* only needed for Emerald Mine II levels */
639 fix_copyright = TRUE;
642 /* ---------- this cave has V3 file format ---------- */
643 file_version = FILE_VERSION_EM_V3;
645 else if (filename_has_v1_format(filename))
647 /* ---------- this cave has V1 file format ---------- */
648 file_version = FILE_VERSION_EM_V1;
652 /* ---------- this cave has V2 file format ---------- */
653 file_version = FILE_VERSION_EM_V2;
656 /* remap elements to internal EMC level format */
657 for (i = 0; i < 2048; i++)
658 src[i] = map_v4[src[i]];
659 for (i = 2048; i < 2084; i++)
660 src[i] = map_v4_eater[src[i] >= 28 ? 0 : src[i]];
661 for (i = 2112; i < 2148; i++)
662 src[i] = src[i - 64];
664 if (fix_copyright) /* fix "(c)" sign in Emerald Mine II levels */
666 for (i = 0; i < 2048; i++)
668 src[i] = 254; /* replace 'Xdecor_1' with 'Xalpha_copyr' */
673 /* ---------- this cave has unknown file format ---------- */
675 /* if file has length of old-style level file, print (wrong) magic byte */
677 Error(ERR_WARN, "unknown magic byte 0x%02x at position 0x%04x",
680 return FILE_VERSION_EM_UNKNOWN;
683 if (file_version < FILE_VERSION_EM_V6)
686 src[2106] = 255; /* version id: */
687 src[2107] = 54; /* '6' */
688 src[2108] = 48; /* '0' */
689 src[2109] = 48; /* '0' */
693 /* stored level time of levels for the V2 player was changed to 50% of the
694 time for the V1 player (original V3 levels already considered this) */
695 if (file_version != FILE_VERSION_EM_V1 &&
696 file_version != FILE_VERSION_EM_V3)
701 for (i = 2148; i < 2172; i++)
708 /* ---------- at this stage, the cave data always has V6 format ---------- */
711 for (i = 0; i < 2048; i++)
714 for (i++; i < 2048; i++)
719 for (i = 64; i < 2048; i++)
720 if (src[i] == 63) /* replace element above 'Xacid_s' ... */
721 src[i - 64] = 101; /* ... with 'Xacid_1' */
723 /* fix acid with no base beneath it (see below for details (*)) */
724 for (i = 64; i < 2048 - 1; i++)
726 if (file_version <= FILE_VERSION_EM_V2 &&
727 src[i - 64] == 101 && src[i] != 63) /* acid without base */
729 if (src[i - 1] == 101 || /* remove acid over acid row */
731 src[i - 64] = 6; /* replace element above with 'Xblank' */
733 src[i - 64] = 255; /* replace element above with 'Xfake_acid_1' */
737 /* fix acid in eater 1 */
738 for (i = 2051; i < 2057; i++)
742 /* fix acid in eater 2 */
743 for (i = 2060; i < 2066; i++)
747 /* fix acid in eater 3 */
748 for (i = 2069; i < 2075; i++)
752 /* fix acid in eater 4 */
753 for (i = 2078; i < 2084; i++)
757 /* fix acid in eater 5 */
758 for (i = 2115; i < 2121; i++)
762 /* fix acid in eater 6 */
763 for (i = 2124; i < 2130; i++)
767 /* fix acid in eater 7 */
768 for (i = 2133; i < 2139; i++)
772 /* fix acid in eater 8 */
773 for (i = 2142; i < 2148; i++)
782 src[src[2096] << 8 | src[2097]] = 128;
786 src[src[2098] << 8 | src[2099]] = 128;
789 if ((src[2100] << 8 | src[2101]) > 9999)
795 /* time wonderwall */
796 if ((src[2102] << 8 | src[2103]) > 9999)
803 if ((src[2110] << 8 | src[2111]) > 9999)
816 if ((src[2154] << 8 | src[2155]) > 9999)
823 if ((src[2156] << 8 | src[2157]) > 9999)
831 src[2159] = map_v6[src[2159]];
834 if ((src[2160] << 8 | src[2161]) > 9999)
845 /* android move pause */
846 if ((src[2164] << 8 | src[2165]) > 9999)
852 /* android clone pause */
853 if ((src[2166] << 8 | src[2167]) > 9999)
862 /* size of v6 cave */
866 Error(ERR_DEBUG, "EM level file version: %d", file_version);
875 structure of emerald mine level disk files
876 ----------------------------------------------------------------------
878 if(len >= 2172 && (buf[2106] == 255 && buf[2107] == 54 && buf[2108] == 48 && buf[2109] == 48)) // v6
879 if(len >= 2110 && (buf[2106] == 255 && buf[2107] == 53 && buf[2108] == 48 && buf[2109] == 48)) // v5
880 if(len >= 2106 && (buf[1983] == 116 || buf[2047] == 116)) // v4
881 if(len >= 2106 && (buf[1983] == 27 || buf[2047] == 219)) // v3
883 buf[0]=241;buf[1]=248;for(i=0,j=101;i<2106;i++,j+=7)buf[i]=(buf[i]^j)-17; // decrypt
885 number of movements (calls to logic) = time * 50 / 8
887 {} reserved (but some broken levels use them)
889 ----------------------------------------------------------------------
909 2095: emeralds needed
913 2102: wonderwall time
915 2106: ID (0xff363030)
921 2148: flags bit#7=NOI #6=RIS
922 2149: wind direction bit#0=right #1=down #2=left #3=up
923 2150: cave number bit#7=teamwork
932 2162: ball info bit#15=switch state #8=random
933 ; bit#0=N #1=S #2=W #3=E #4=SE #5=SW #6=NE #7=NW
934 2164: android move speed
935 2166: android clone speed
937 ; bit#0=emerald #1=diamond #2=stone #3=bomb #4=nut #5=tank #6=eater
938 ; #7=bug #8=alien #9=spring #10=balloon #11=ameuba #12=dynamite
943 1: stone {stone_fall}
945 3: diamond {diamond_fall}
947 5: alien {alien_pause}
961 19: emerald {emerald_fall}
972 30: blank {drip_stretchB}
973 31: drip {drip_stretch}
974 32: stone {stone_pause}
975 33: bomb {bomb_pause}
976 34: diamond {diamond_pause}
977 35: emerald {emerald_pause}
978 36: wonderwall {wonderwallB}
988 46: blank {sand_stonein_2}
989 47: blank {sand_stonein_3}
990 48: blank {sand_stonein_4}
991 49: sand {sand_stonesand_2}
992 50: sand {sand_stonesand_3}
993 51: sand {sand_stonesand_4}
994 52: sand_stone {sand_sandstone_2}
995 53: sand_stone {sand_sandstone_3}
996 54: sand_stone {sand_sandstone_4}
997 55: sand {sand_stonesand_4}
998 56: stone {sand_stoneout_2}
1012 70: spring {spring_fall}
1013 71: spring {spring_w}
1014 72: spring {spring_e}
1019 77: android {android_n_1}
1020 78: android {android_n_2}
1021 79: android {android_s_1}
1022 80: android {android_s_2}
1023 81: android {android_e_1}
1024 82: android {android_e_2}
1025 83: android {android_w_1}
1026 84: android {android_w_2}
1041 99: spring {push_spring_w}
1042 100: spring {push_spring_e}
1051 109: pause {grass_wB}
1052 110: pause {grass_eB}
1053 111: pause {grass_nB}
1054 112: pause {grass_sB}
1055 113: pause {dynamite_blank}
1056 114: nut {push_nut_w}
1057 115: nut {push_nut_e}
1058 116: steel_2 {end of level}
1060 118: pause {emerald_blank}
1061 119: bomb {push_bomb_w}
1062 120: bomb {push_bomb_e}
1063 121: stone {push_stone_w}
1064 122: stone {push_stone_e}
1065 123: pause {diamond_blank}
1066 124: pause {dirt_wB}
1067 125: pause {dirt_eB}
1068 126: pause {dirt_nB}
1069 127: pause {dirt_sB}
1106 163: fake_blank {fake_blankB}
1107 164: fake_grass {fake_grassB}
1109 166: switch {switchB}
1200 ----------------------------------------------------------------------
1216 2091: dynamite value
1220 2095: emeralds needed
1224 2102: wonderwall time
1226 2106: ID (0xff353030)
1230 1: stone {stone_fall}
1232 3: diamond {diamond_fall}
1234 5: alien {alien_pause}
1246 17: bomb {bomb_fall}
1248 19: emerald {emerald_fall}
1258 29: drip {drip_fall}
1259 30: blank {drip_stretchB}
1260 31: drip {drip_stretch}
1261 32: stone {stone_pause}
1262 33: bomb {bomb_pause}
1263 34: diamond {diamond_pause}
1264 35: emerald {emerald_pause}
1265 36: wonderwall {wonderwallB}
1275 46: blank {sand_stonein_2}
1276 47: blank {sand_stonein_3}
1277 48: blank {sand_stonein_4}
1278 49: sand {sand_stonesand_2}
1279 50: sand {sand_stonesand_3}
1280 51: sand {sand_stonesand_4}
1281 52: sand_stone {sand_sandstone_2}
1282 53: sand_stone {sand_sandstone_3}
1283 54: sand_stone {sand_sandstone_4}
1284 55: sand {sand_stonesand_4}
1285 56: stone {sand_stoneout_2}
1338 109: pause {grass_wB}
1339 110: pause {grass_eB}
1340 111: pause {grass_nB}
1341 112: pause {grass_sB}
1342 113: pause {dynamite_blank}
1343 114: nut {push_nut_w}
1344 115: nut {push_nut_e}
1345 116: steel_2 {end of level}
1346 117: dynamite_4 {boom_2}
1347 118: pause {emerald_blank}
1348 119: bomb {push_bomb_w}
1349 120: bomb {push_bomb_e}
1350 121: stone {push_stone_w}
1351 122: stone {push_stone_e}
1352 123: pause {diamond_blank}
1353 124: pause {dirt_wB}
1354 125: pause {dirt_eB}
1355 126: pause {dirt_nB}
1356 127: pause {dirt_sB}
1487 ----------------------------------------------------------------------
1503 2091: dynamite value
1507 2095: emeralds needed
1511 2102: wonderwall time
1541 26: diamond {diamond_shine}
1542 27: emerald {emerald_shine}
1545 1: stone {stone_fall}
1547 3: diamond {diamond_fall}
1549 5: alien {alien_pause}
1561 17: bomb {bomb_fall}
1563 19: emerald {emerald_fall}
1573 29: drip {drip_fall}
1574 30: blank {drip_stretchB}
1575 31: drip {drip_stretch}
1576 32: stone {stone_pause}
1577 33: bomb {bomb_pause}
1578 34: diamond {diamond_pause}
1579 35: emerald {emerald_pause}
1580 36: wonderwall {wonderwallB}
1590 46: blank {sand_stonein_2}
1591 47: blank {sand_stonein_3}
1592 48: blank {sand_stonein_4}
1593 49: sand {sand_stonesand_2}
1594 50: sand {sand_stonesand_3}
1595 51: sand {sand_stonesand_4}
1596 52: sand_stone {sand_sandstone_2}
1597 53: sand_stone {sand_sandstone_3}
1598 54: sand_stone {sand_sandstone_4}
1599 55: sand {sand_stonesand_4}
1600 56: stone {sand_stoneout_2}
1657 113: pause {dynamite_blank}
1658 114: nut {push_nut_w}
1659 115: nut {push_nut_e}
1660 116: steel_1 {end of level}
1661 117: dynamite_4 {boom_2}
1662 118: pause {emerald_blank}
1663 119: bomb {push_bomb_w}
1664 120: bomb {push_bomb_e}
1665 121: stone {push_stone_w}
1666 122: stone {push_stone_e}
1667 123: pause {diamond_blank}
1668 124: pause {dirt_wB}
1669 125: pause {dirt_eB}
1670 126: pause {dirt_nB}
1671 127: pause {dirt_sB}
1704 159: fake_grass {dirt}
1705 160: fake_grass {dirt}
1706 161: fake_grass {dirt}
1707 162: fake_grass {dirt}
1708 163: fake_grass {dirt}
1709 164: fake_grass {dirt}
1710 165: fake_grass {dirt}
1711 166: fake_grass {dirt}
1712 167: fake_grass {dirt}
1713 168: fake_grass {dirt}
1714 169: fake_grass {dirt}
1715 170: fake_grass {dirt}
1716 171: fake_grass {dirt}
1717 172: fake_grass {dirt}
1718 173: fake_grass {dirt}
1719 174: fake_grass {dirt}
1785 240: alpha_arrow_e {}
1786 241: decor_1 {alpha_copyr}
1802 ----------------------------------------------------------------------