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])
45 static const short map_emc[256] =
47 Xstone, Xstone, Xdiamond, Xdiamond,
48 Xalien, Xalien, Xblank, Xblank,
49 Xtank_1_n, Xtank_1_e, Xtank_1_s, Xtank_1_w,
50 Xtank_2_n, Xtank_2_e, Xtank_2_s, Xtank_2_w,
52 Xbomb, Xbomb, Xemerald, Xemerald,
53 Xbug_1_n, Xbug_1_e, Xbug_1_s, Xbug_1_w,
54 Xbug_2_n, Xbug_2_e, Xbug_2_s, Xbug_2_w,
55 Xdrip, Xdrip, Xdrip, Xdrip,
57 Xstone, Xbomb, Xdiamond, Xemerald,
58 Xwonderwall, Xnut, Xnut, Xnut,
59 Xwheel, Xeater_n, Xeater_s, Xeater_w,
60 Xeater_e, Xsand_stone, Xblank, Xblank,
62 Xblank, Xsand, Xsand, Xsand,
63 Xsand_stone, Xsand_stone, Xsand_stone, Xsand,
64 Xstone, Xslide_ew, Xslide_ns, Xdynamite_1,
65 Xdynamite_2, Xdynamite_3, Xdynamite_4, Xacid_s,
67 Xexit_1, Xexit_2, Xexit_3, Xballoon,
68 Xplant, Xspring, Xspring_fall, Xspring_w,
69 Xspring_e, Xball_1, Xball_2, Xandroid,
70 Xblank, Xandroid, Xandroid, Xandroid,
72 Xandroid, Xandroid, Xandroid, Xandroid,
73 Xandroid, Xblank, Xblank, Xblank,
74 Xblank, Xblank, Xblank, Xblank,
75 Xblank, Xblank, Xblank, Xblank,
77 Xblank, Xblank, Xblank, Xpush_spring_w,
78 Xpush_spring_e, Xacid_1, Xacid_2, Xacid_3,
79 Xacid_4, Xacid_5, Xacid_6, Xacid_7,
80 Xacid_8, Xblank, Xblank, Xblank,
82 Xblank, Xblank, Xpush_nut_w, Xpush_nut_e,
83 Xsteel_1, Xblank, Xblank, Xpush_bomb_w,
84 Xpush_bomb_e, Xpush_stone_w, Xpush_stone_e, Xblank,
85 Xblank, Xblank, Xblank, Xblank,
87 Xblank, Xroundwall_1, Xgrass, Xsteel_1,
88 Xwall_1, Xkey_1, Xkey_2, Xkey_3,
89 Xkey_4, Xdoor_1, Xdoor_2, Xdoor_3,
90 Xdoor_4, Xfake_amoeba, Xfake_door_1, Xfake_door_2,
92 Xfake_door_3, Xfake_door_4, Xwonderwall, Xwheel,
93 Xsand, Xacid_nw, Xacid_ne, Xacid_sw,
94 Xacid_se, Xfake_blank, Xamoeba_1, Xamoeba_2,
95 Xamoeba_3, Xamoeba_4, Xexit, Xalpha_arrow_w,
97 Xfake_grass, Xlenses, Xmagnify, Xfake_blank,
98 Xfake_grass, Xswitch, Xswitch, Xblank,
99 Xdecor_8, Xdecor_9, Xdecor_10, Xdecor_5,
100 Xalpha_comma, Xalpha_quote, Xalpha_minus, Xdynamite,
102 Xsteel_3, Xdecor_6, Xdecor_7, Xsteel_2,
103 Xroundwall_2, Xdecor_2, Xdecor_4, Xdecor_3,
104 Xwind_any, Xwind_e, Xwind_s, Xwind_w,
105 Xwind_n, Xdirt, Xplant, Xkey_5,
107 Xkey_6, Xkey_7, Xkey_8, Xdoor_5,
108 Xdoor_6, Xdoor_7, Xdoor_8, Xbumper,
109 Xalpha_a, Xalpha_b, Xalpha_c, Xalpha_d,
110 Xalpha_e, Xalpha_f, Xalpha_g, Xalpha_h,
112 Xalpha_i, Xalpha_j, Xalpha_k, Xalpha_l,
113 Xalpha_m, Xalpha_n, Xalpha_o, Xalpha_p,
114 Xalpha_q, Xalpha_r, Xalpha_s, Xalpha_t,
115 Xalpha_u, Xalpha_v, Xalpha_w, Xalpha_x,
117 Xalpha_y, Xalpha_z, Xalpha_0, Xalpha_1,
118 Xalpha_2, Xalpha_3, Xalpha_4, Xalpha_5,
119 Xalpha_6, Xalpha_7, Xalpha_8, Xalpha_9,
120 Xalpha_perio, Xalpha_excla, Xalpha_colon, Xalpha_quest,
122 Xalpha_arrow_e, Xdecor_1, Xfake_door_5, Xfake_door_6,
123 Xfake_door_7, Xfake_door_8, Xblank, Xblank,
124 Xblank, Xblank, Xblank, Xblank,
125 Xblank, Xblank, Xalpha_copyr, Xfake_acid_1
128 static void init_android_clone_table(short android_clone_bits)
130 boolean android_emerald = (android_clone_bits & 1) != 0;
131 boolean android_diamond = (android_clone_bits & 2) != 0;
132 boolean android_stone = (android_clone_bits & 4) != 0;
133 boolean android_bomb = (android_clone_bits & 8) != 0;
134 boolean android_nut = (android_clone_bits & 16) != 0;
135 boolean android_tank = (android_clone_bits & 32) != 0;
136 boolean android_eater = (android_clone_bits & 64) != 0;
137 boolean android_bug = (android_clone_bits & 128) != 0;
138 boolean android_alien = (android_clone_bits & 256) != 0;
139 boolean android_spring = (android_clone_bits & 512) != 0;
140 boolean android_balloon = (android_clone_bits & 1024) != 0;
141 boolean android_amoeba = (android_clone_bits & 2048) != 0;
142 boolean android_dynamite = (android_clone_bits & 4096) != 0;
145 for (i = 0; i < TILE_MAX; i++)
146 cav.android_array[i] = Xblank;
150 cav.android_array[Xeater_n] = Xeater_n;
151 cav.android_array[Yeater_nB] = Xeater_n;
153 cav.android_array[Xeater_e] = Xeater_e;
154 cav.android_array[Yeater_eB] = Xeater_e;
156 cav.android_array[Xeater_s] = Xeater_s;
157 cav.android_array[Yeater_sB] = Xeater_s;
159 cav.android_array[Xeater_w] = Xeater_w;
160 cav.android_array[Yeater_wB] = Xeater_w;
165 cav.android_array[Xalien] = Xalien;
166 cav.android_array[Xalien_pause] = Xalien;
167 cav.android_array[Yalien_nB] = Xalien;
168 cav.android_array[Yalien_eB] = Xalien;
169 cav.android_array[Yalien_sB] = Xalien;
170 cav.android_array[Yalien_wB] = Xalien;
175 cav.android_array[Xbug_1_n] = Xbug_2_n;
176 cav.android_array[Xbug_2_n] = Xbug_2_n;
177 cav.android_array[Ybug_nB] = Xbug_2_n;
178 cav.android_array[Ybug_n_e] = Xbug_2_n;
179 cav.android_array[Ybug_n_w] = Xbug_2_n;
181 cav.android_array[Xbug_1_e] = Xbug_2_e;
182 cav.android_array[Xbug_2_e] = Xbug_2_e;
183 cav.android_array[Ybug_eB] = Xbug_2_e;
184 cav.android_array[Ybug_e_s] = Xbug_2_e;
185 cav.android_array[Ybug_e_n] = Xbug_2_e;
187 cav.android_array[Xbug_1_s] = Xbug_2_s;
188 cav.android_array[Xbug_2_s] = Xbug_2_s;
189 cav.android_array[Ybug_sB] = Xbug_2_s;
190 cav.android_array[Ybug_s_w] = Xbug_2_s;
191 cav.android_array[Ybug_s_e] = Xbug_2_s;
193 cav.android_array[Xbug_1_w] = Xbug_2_w;
194 cav.android_array[Xbug_2_w] = Xbug_2_w;
195 cav.android_array[Ybug_wB] = Xbug_2_w;
196 cav.android_array[Ybug_w_n] = Xbug_2_w;
197 cav.android_array[Ybug_w_s] = Xbug_2_w;
202 cav.android_array[Xtank_1_n] = Xtank_1_n;
203 cav.android_array[Xtank_2_n] = Xtank_1_n;
204 cav.android_array[Ytank_nB] = Xtank_1_n;
205 cav.android_array[Ytank_n_e] = Xtank_1_n;
206 cav.android_array[Ytank_n_w] = Xtank_1_n;
208 cav.android_array[Xtank_1_e] = Xtank_1_e;
209 cav.android_array[Xtank_2_e] = Xtank_1_e;
210 cav.android_array[Ytank_eB] = Xtank_1_e;
211 cav.android_array[Ytank_e_s] = Xtank_1_e;
212 cav.android_array[Ytank_e_n] = Xtank_1_e;
214 cav.android_array[Xtank_1_s] = Xtank_1_s;
215 cav.android_array[Xtank_2_s] = Xtank_1_s;
216 cav.android_array[Ytank_sB] = Xtank_1_s;
217 cav.android_array[Ytank_s_w] = Xtank_1_s;
218 cav.android_array[Ytank_s_e] = Xtank_1_s;
220 cav.android_array[Xtank_1_w] = Xtank_1_w;
221 cav.android_array[Xtank_2_w] = Xtank_1_w;
222 cav.android_array[Ytank_wB] = Xtank_1_w;
223 cav.android_array[Ytank_w_n] = Xtank_1_w;
224 cav.android_array[Ytank_w_s] = Xtank_1_w;
229 cav.android_array[Xemerald] = Xemerald;
230 cav.android_array[Xemerald_pause] = Xemerald;
231 cav.android_array[Xemerald_fall] = Xemerald;
232 cav.android_array[Yemerald_sB] = Xemerald;
233 cav.android_array[Yemerald_eB] = Xemerald;
234 cav.android_array[Yemerald_wB] = Xemerald;
239 cav.android_array[Xdiamond] = Xdiamond;
240 cav.android_array[Xdiamond_pause] = Xdiamond;
241 cav.android_array[Xdiamond_fall] = Xdiamond;
242 cav.android_array[Ydiamond_sB] = Xdiamond;
243 cav.android_array[Ydiamond_eB] = Xdiamond;
244 cav.android_array[Ydiamond_wB] = Xdiamond;
249 cav.android_array[Xstone] = Xstone;
250 cav.android_array[Xstone_pause] = Xstone;
251 cav.android_array[Xstone_fall] = Xstone;
252 cav.android_array[Ystone_sB] = Xstone;
253 cav.android_array[Ystone_eB] = Xstone;
254 cav.android_array[Ystone_wB] = Xstone;
259 cav.android_array[Xbomb] = Xbomb;
260 cav.android_array[Xbomb_pause] = Xbomb;
261 cav.android_array[Xbomb_fall] = Xbomb;
262 cav.android_array[Ybomb_sB] = Xbomb;
263 cav.android_array[Ybomb_eB] = Xbomb;
264 cav.android_array[Ybomb_wB] = Xbomb;
269 cav.android_array[Xnut] = Xnut;
270 cav.android_array[Xnut_pause] = Xnut;
271 cav.android_array[Xnut_fall] = Xnut;
272 cav.android_array[Ynut_sB] = Xnut;
273 cav.android_array[Ynut_eB] = Xnut;
274 cav.android_array[Ynut_wB] = Xnut;
279 cav.android_array[Xspring] = Xspring;
280 cav.android_array[Xspring_pause] = Xspring;
281 cav.android_array[Xspring_fall] = Xspring;
282 cav.android_array[Xspring_e] = Xspring;
283 cav.android_array[Xspring_w] = Xspring;
284 cav.android_array[Yspring_sB] = Xspring;
285 cav.android_array[Yspring_eB] = Xspring;
286 cav.android_array[Yspring_wB] = Xspring;
287 cav.android_array[Yspring_alien_eB] = Xspring;
288 cav.android_array[Yspring_alien_wB] = Xspring;
291 if (android_dynamite)
293 cav.android_array[Xdynamite] = Xdynamite;
298 cav.android_array[Xballoon] = Xballoon;
299 cav.android_array[Yballoon_nB] = Xballoon;
300 cav.android_array[Yballoon_eB] = Xballoon;
301 cav.android_array[Yballoon_sB] = Xballoon;
302 cav.android_array[Yballoon_wB] = Xballoon;
307 cav.android_array[Xfake_amoeba] = Xdrip;
308 cav.android_array[Yfake_amoeba] = Xdrip;
309 cav.android_array[Xamoeba_1] = Xdrip;
310 cav.android_array[Xamoeba_2] = Xdrip;
311 cav.android_array[Xamoeba_3] = Xdrip;
312 cav.android_array[Xamoeba_4] = Xdrip;
313 cav.android_array[Xamoeba_5] = Xdrip;
314 cav.android_array[Xamoeba_6] = Xdrip;
315 cav.android_array[Xamoeba_7] = Xdrip;
316 cav.android_array[Xamoeba_8] = Xdrip;
320 void convert_em_level(unsigned char *src, int file_version)
322 static int eater_offset[8] =
324 2048, 2057, 2066, 2075,
325 2112, 2121, 2130, 2139
329 /* common to all emc caves */
331 cav.time_seconds = MIN(GET_BE16(src[2110]), 9999);
332 cav.gems_needed = src[2095];
336 cav.emerald_score = src[2084];
337 cav.diamond_score = src[2085];
338 cav.alien_score = src[2086];
339 cav.tank_score = src[2087];
340 cav.bug_score = src[2088];
341 cav.eater_score = src[2089];
342 cav.nut_score = src[2090];
343 cav.dynamite_score = src[2091];
344 cav.key_score = src[2092];
345 cav.exit_score = src[2093] * 8 / 5;
347 cav.lenses_score = src[2151];
348 cav.magnify_score = src[2152];
349 cav.slurp_score = src[2153];
353 cav.android_move_time = MIN(GET_BE16(src[2164]), 9999);
354 cav.android_clone_time = MIN(GET_BE16(src[2166]), 9999);
355 cav.ball_time = MIN(GET_BE16(src[2160]), 9999);
357 cav.lenses_time = MIN(GET_BE16(src[2154]), 9999);
358 cav.magnify_time = MIN(GET_BE16(src[2156]), 9999);
359 cav.wheel_time = MIN(GET_BE16(src[2104]), 9999);
361 cav.amoeba_time = MIN(GET_BE16(src[2100]) * 28, 9999);
362 cav.wonderwall_time = MIN(GET_BE16(src[2102]), 9999);
364 cav.wind_cnt = src[2149] & 15 ? cav.wind_time : 0;
366 cav.wind_direction = (temp & 8 ? 0 :
373 cav.ball_random = src[2162] & 1 ? 1 : 0;
374 cav.ball_state = src[2162] & 128 ? 1 : 0;
376 for (temp = 1; temp < 2047; temp++)
380 case 36: /* wonderwall */
381 cav.wonderwall_state = 1;
382 cav.wonderwall_time = 9999;
386 cav.wheel_x = temp & 63;
387 cav.wheel_y = temp >> 6;
388 cav.wheel_cnt = cav.wheel_time;
391 case 163: /* fake blank */
392 cav.lenses_cnt = 9999;
395 case 164: /* fake grass */
396 cav.magnify_cnt = 9999;
403 init_android_clone_table(GET_BE16(src[2168]));
407 for (i = 0; i < 8; i++)
408 for (x = 0; x < 9; x++)
409 cav.eater_array[i][x] = map_emc[src[eater_offset[i] + x]];
413 temp = map_emc[src[2159]];
415 for (y = 0; y < 8; y++)
419 for (x = 0; x < 8; x++)
420 cav.ball_array[y][x] = temp;
424 cav.ball_array[y][1] = (src[2163] & 1) ? temp : Xblank; /* north */
425 cav.ball_array[y][6] = (src[2163] & 2) ? temp : Xblank; /* south */
426 cav.ball_array[y][3] = (src[2163] & 4) ? temp : Xblank; /* west */
427 cav.ball_array[y][4] = (src[2163] & 8) ? temp : Xblank; /* east */
428 cav.ball_array[y][7] = (src[2163] & 16) ? temp : Xblank; /* southeast */
429 cav.ball_array[y][5] = (src[2163] & 32) ? temp : Xblank; /* southwest */
430 cav.ball_array[y][2] = (src[2163] & 64) ? temp : Xblank; /* northeast */
431 cav.ball_array[y][0] = (src[2163] & 128)? temp : Xblank; /* northwest */
437 for (i = 0; i < 2; i++)
439 temp = GET_BE16(src[2096 + i * 2]);
441 cav.player_x[i] = (temp & 63);
442 cav.player_y[i] = (temp >> 6 & 31);
447 /* first fill the complete playfield with the default border element */
448 for (y = 0; y < CAVE_HEIGHT; y++)
449 for (x = 0; x < CAVE_WIDTH; x++)
450 cav.cave[x][y] = Zborder;
452 /* then copy the real level contents from level file into the playfield */
454 for (y = 0; y < cav.height; y++)
455 for (x = 0; x < cav.width; x++)
456 cav.cave[x][y] = map_emc[src[temp++]];
458 /* at last, set the two players at their positions in the playfield */
459 /* (native EM[C] levels always have exactly two players in a level) */
460 for (i = 0; i < 2; i++)
461 cav.cave[cav.player_x[i]][cav.player_y[i]] = Zplayer;
463 native_em_level.file_version = file_version;
467 /* convert all emerald mine caves to emc version 6 cave format.
469 * caves are filtered to get rid of invalid or unsupported tiles.
471 * although the result is a somewhat clean cave, it is meant only
472 * to give a common structure for the binary cave format. it is not
473 * for archiving purposes (it is better to keep the raw cave as-is)
474 * and it is not meant for serializing (the intermediate structure
475 * is better defined).
477 * acid top is added to acid bottom in both the cave and the eaters.
478 * fake acid (only in v4) does not exist because it adds nothing to
479 * the game, and is different even in different versions of the emc
482 * v4/v5 time is converted to 10x old time (as it should be).
483 * the reason the kingsoft player used 5x time was copy protection.
485 * note: emc v6 converter has an error in converting v4 eaters to the
486 * wrong bug(24 instead of 20) and tank(12 instead of 8).
489 /* changes for game engine integration in Rocks'n'Diamonds:
491 * cave versions below V5 had no grass, but only sand/dirt
492 * - object code 130 (V6 grass) is changed to 189 (V6 dirt)
493 * - object codes are changed in both cave and eater arrays
494 * - only graphical change, as both objects behave the same
497 static const unsigned char map_v6[256] =
501 0,0,2,2, 4,4,118,118, 8,9,10,11, 12,13,14,15,
502 16,16,18,18, 20,21,22,23, 24,25,26,27, 28,28,118,28,
503 0,16,2,18, 36,37,37,37, 40,41,42,43, 44,45,128,128,
504 128,148,148, 148,45,45,45, 148,0,57,58, 59,60,61,62,63,
506 64,65,66,67, 68,69,69,71, 72,73,74,75, 118,75,75,75,
507 75,75,75,75, 75,153,153,153, 153,153,153,153, 153,153,153,153,
508 153,153,153,99, 100,68,68,68, 68,68,68,68, 68,118,118,118,
509 118,118,114,115, 131,118,118,119, 120,121,122,118, 118,118,118,118,
511 128,129,130,131, 132,133,134,135, 136,137,138,139, 140,141,142,143,
512 144,145,146,147, 148,149,150,151, 152,153,154,155, 156,157,158,159,
513 160,161,162,163, 164,165,165,118, 168,169,170,171, 172,173,174,175,
514 176,177,178,179, 180,181,182,183, 184,185,186,187, 188,189,68,191,
516 192,193,194,195, 196,197,198,199, 200,201,202,203, 204,205,206,207,
517 208,209,210,211, 212,213,214,215, 216,217,218,219, 220,221,222,223,
518 224,225,226,227, 228,229,230,231, 232,233,234,235, 236,237,238,239,
519 240,241,242,243, 244,245,153,153, 153,153,153,153, 153,153,153,153
522 static const unsigned char map_v5[256] =
526 0,0,2,2, 4,4,118,118, 8,9,10,11, 12,13,14,15,
527 16,16,18,18, 20,21,22,23, 24,25,26,27, 28,28,118,28,
528 0,16,2,18, 36,37,37,37, 147,41,42,43, 44,45,128,128,
529 128,148,148,148, 45,45,45,148, 0,57,58,59, 60,61,62,63,
531 64,65,66,67, 68,153,153,153, 153,153,153,153, 153,153,153,153,
532 153,153,153,153, 153,153,153,153, 153,153,153,153, 153,153,153,153,
533 153,153,153,153, 153,68,68,68, 68,68,68,68, 68,118,118,118,
534 118,118,114,115, 131,118,118,119, 120,121,122,118, 118,118,118,118,
536 128,129,130,131, 132,133,134,135, 136,137,138,139, 140,141,142,143,
537 144,145,146,147, 148,149,150,151, 152,153,154,155, 156,157,158,159,
538 160,153,153,153, 153,153,153,118, 168,169,170,171, 172,173,174,175,
539 176,177,178,179, 180,181,182,183, 184,185,186,187, 188,189,68,153,
541 153,153,153,153, 153,153,153,153, 200,201,202,203, 204,205,206,207,
542 208,209,210,211, 212,213,214,215, 216,217,218,219, 220,221,222,223,
543 224,225,226,227, 228,229,230,231, 232,233,234,235, 236,237,238,239,
544 240,241,153,153, 153,153,153,153, 153,153,153,153, 153,153,153,153
547 static const unsigned char map_v4[256] =
551 0,0,2,2, 4,4,118,118, 8,9,10,11, 12,13,14,15,
552 16,16,18,18, 20,21,22,23, 24,25,26,27, 28,28,118,28,
553 0,16,2,18, 36,37,37,37, 147,41,42,43, 44,45,128,128,
554 128,148,148,148, 45,45,45,148, 0,153,153,59, 60,61,62,63,
556 64,65,66,153, 153,153,153,153, 153,153,153,153, 153,153,153,153,
557 153,153,153,153, 153,153,153,153, 153,153,153,153, 153,153,153,153,
558 153,153,153,153, 153,153,153,153, 153,153,153,153, 153,153,153,153,
559 153,118,114,115, 131,118,118,119, 120,121,122,118, 118,118,118,118,
561 128,129,189,131, 132,133,134,135, 136,137,138,139, 140,141,142,143,
562 144,145,146,147, 148,149,150,151, 152,68,154,155, 156,157,158,160,
563 160,160,160,160, 160,160,160,160, 160,160,160,160, 160,160,160,175,
564 153,153,153,153, 153,153,153,153, 153,153,153,153, 153,153,68,153,
566 153,153,153,153, 153,153,153,153, 200,201,202,203, 204,205,206,207,
567 208,209,210,211, 212,213,214,215, 216,217,218,219, 220,221,222,223,
568 224,225,226,227, 228,229,230,231, 232,233,234,235, 236,237,238,239,
569 240,241,153,153, 153,153,153,153, 153,153,153,153, 153,153,153,153
572 static const unsigned char map_v4_eater[32] =
574 /* filter for v4 eater */
576 128,18,2,0, 4,8,16,20, 28,37,41,45, 189,129,131,132,
577 133,134,135,136, 146,147,175,65, 66,64,2,18, 128,128,128,128
580 static boolean filename_has_v1_format(char *filename)
582 char *basename = getBaseNamePtr(filename);
584 return (strlen(basename) == 3 &&
585 basename[0] == 'a' &&
586 basename[1] >= 'a' && basename[1] <= 'k' &&
587 basename[2] >= '0' && basename[2] <= '9');
590 int cleanup_em_level(unsigned char *src, int length, char *filename)
592 int file_version = FILE_VERSION_EM_UNKNOWN;
595 if (length >= 2172 &&
596 src[2106] == 255 && /* version id: */
597 src[2107] == 54 && /* '6' */
598 src[2108] == 48 && /* '0' */
599 src[2109] == 48) /* '0' */
601 /* ---------- this cave has V6 file format ---------- */
602 file_version = FILE_VERSION_EM_V6;
604 /* remap elements to internal EMC level format */
605 for (i = 0; i < 2048; i++)
606 src[i] = map_v6[src[i]];
607 for (i = 2048; i < 2084; i++)
608 src[i] = map_v6[src[i]];
609 for (i = 2112; i < 2148; i++)
610 src[i] = map_v6[src[i]];
612 else if (length >= 2110 &&
613 src[2106] == 255 && /* version id: */
614 src[2107] == 53 && /* '5' */
615 src[2108] == 48 && /* '0' */
616 src[2109] == 48) /* '0' */
618 /* ---------- this cave has V5 file format ---------- */
619 file_version = FILE_VERSION_EM_V5;
621 /* remap elements to internal EMC level format */
622 for (i = 0; i < 2048; i++)
623 src[i] = map_v5[src[i]];
624 for (i = 2048; i < 2084; i++)
625 src[i] = map_v5[src[i]];
626 for (i = 2112; i < 2148; i++)
627 src[i] = src[i - 64];
629 else if (length >= 2106 &&
630 (src[1983] == 27 || /* encrypted (only EM I/II/III) */
631 src[1983] == 116 || /* unencrypted (usual case) */
632 src[1983] == 131)) /* unencrypted (rare case) */
634 /* ---------- this cave has V1, V2 or V3 file format ---------- */
636 boolean fix_copyright = FALSE;
639 byte at position 1983 (0x07bf) is used as "magic byte":
640 - 27 (0x1b) => encrypted level (V3 only / Kingsoft original games)
641 - 116 (0x74) => unencrypted level (byte is corrected to 131 (0x83))
642 - 131 (0x83) => unencrypted level (happens only in very rare cases)
645 if (src[1983] == 27) /* (0x1b) -- after decryption: 116 (0x74) */
647 /* this is original (encrypted) Emerald Mine I, II or III level file */
649 int first_byte = src[0];
650 unsigned char code0 = 0x65;
651 unsigned char code1 = 0x11;
653 /* decode encrypted level data */
654 for (i = 0; i < 2106; i++)
659 code0 = (code0 + 7) & 0xff;
662 src[1] = 131; /* needed for all Emerald Mine levels */
664 /* first byte is either 0xf1 (EM I and III) or 0xf5 (EM II) */
665 if (first_byte == 0xf5)
667 src[0] = 131; /* only needed for Emerald Mine II levels */
669 fix_copyright = TRUE;
672 /* ---------- this cave has V3 file format ---------- */
673 file_version = FILE_VERSION_EM_V3;
675 else if (filename_has_v1_format(filename))
677 /* ---------- this cave has V1 file format ---------- */
678 file_version = FILE_VERSION_EM_V1;
682 /* ---------- this cave has V2 file format ---------- */
683 file_version = FILE_VERSION_EM_V2;
686 /* remap elements to internal EMC level format */
687 for (i = 0; i < 2048; i++)
688 src[i] = map_v4[src[i]];
689 for (i = 2048; i < 2084; i++)
690 src[i] = map_v4_eater[src[i] >= 28 ? 0 : src[i]];
691 for (i = 2112; i < 2148; i++)
692 src[i] = src[i - 64];
694 if (fix_copyright) /* fix "(c)" sign in Emerald Mine II levels */
696 for (i = 0; i < 2048; i++)
698 src[i] = 254; /* replace 'Xdecor_1' with 'Xalpha_copyr' */
703 /* ---------- this cave has unknown file format ---------- */
705 /* if file has length of old-style level file, print (wrong) magic byte */
707 Error(ERR_WARN, "unknown magic byte 0x%02x at position 0x%04x",
710 return FILE_VERSION_EM_UNKNOWN;
713 if (file_version < FILE_VERSION_EM_V6)
716 src[2106] = 255; /* version id: */
717 src[2107] = 54; /* '6' */
718 src[2108] = 48; /* '0' */
719 src[2109] = 48; /* '0' */
723 /* stored level time of levels for the V2 player was changed to 50% of the
724 time for the V1 player (original V3 levels already considered this) */
725 if (file_version != FILE_VERSION_EM_V1 &&
726 file_version != FILE_VERSION_EM_V3)
731 for (i = 2148; i < 2172; i++)
738 /* ---------- at this stage, the cave data always has V6 format ---------- */
741 for (i = 0; i < 2048; i++)
744 for (i++; i < 2048; i++)
749 for (i = 64; i < 2048; i++)
750 if (src[i] == 63) /* replace element above 'Xacid_s' ... */
751 src[i - 64] = 101; /* ... with 'Xacid_1' */
753 /* fix acid with no base beneath it (see below for details (*)) */
754 for (i = 64; i < 2048 - 1; i++)
756 if (file_version <= FILE_VERSION_EM_V2 &&
757 src[i - 64] == 101 && src[i] != 63) /* acid without base */
759 if (src[i - 1] == 101 || /* remove acid over acid row */
761 src[i - 64] = 6; /* replace element above with 'Xblank' */
763 src[i - 64] = 255; /* replace element above with 'Xfake_acid_1' */
767 /* fix acid in eater 1 */
768 for (i = 2051; i < 2057; i++)
772 /* fix acid in eater 2 */
773 for (i = 2060; i < 2066; i++)
777 /* fix acid in eater 3 */
778 for (i = 2069; i < 2075; i++)
782 /* fix acid in eater 4 */
783 for (i = 2078; i < 2084; i++)
787 /* fix acid in eater 5 */
788 for (i = 2115; i < 2121; i++)
792 /* fix acid in eater 6 */
793 for (i = 2124; i < 2130; i++)
797 /* fix acid in eater 7 */
798 for (i = 2133; i < 2139; i++)
802 /* fix acid in eater 8 */
803 for (i = 2142; i < 2148; i++)
812 src[GET_BE16(src[2096])] = 128;
816 src[GET_BE16(src[2098])] = 128;
826 src[2159] = map_v6[src[2159]];
836 /* size of v6 cave */
840 Error(ERR_DEBUG, "EM level file version: %d", file_version);
849 structure of emerald mine level disk files
850 ----------------------------------------------------------------------
852 if(len >= 2172 && (buf[2106] == 255 && buf[2107] == 54 && buf[2108] == 48 && buf[2109] == 48)) // v6
853 if(len >= 2110 && (buf[2106] == 255 && buf[2107] == 53 && buf[2108] == 48 && buf[2109] == 48)) // v5
854 if(len >= 2106 && (buf[1983] == 116 || buf[2047] == 116)) // v4
855 if(len >= 2106 && (buf[1983] == 27 || buf[2047] == 219)) // v3
857 buf[0]=241;buf[1]=248;for(i=0,j=101;i<2106;i++,j+=7)buf[i]=(buf[i]^j)-17; // decrypt
859 number of movements (calls to logic) = time * 50 / 8
861 {} reserved (but some broken levels use them)
863 ----------------------------------------------------------------------
883 2095: emeralds needed
887 2102: wonderwall time
889 2106: ID (0xff363030)
895 2148: flags bit#7=NOI #6=RIS
896 2149: wind direction bit#0=right #1=down #2=left #3=up
897 2150: cave number bit#7=teamwork
906 2162: ball info bit#15=switch state #8=random
907 ; bit#0=N #1=S #2=W #3=E #4=SE #5=SW #6=NE #7=NW
908 2164: android move speed
909 2166: android clone speed
911 ; bit#0=emerald #1=diamond #2=stone #3=bomb #4=nut #5=tank #6=eater
912 ; #7=bug #8=alien #9=spring #10=balloon #11=ameuba #12=dynamite
917 1: stone {stone_fall}
919 3: diamond {diamond_fall}
921 5: alien {alien_pause}
935 19: emerald {emerald_fall}
946 30: blank {drip_stretchB}
947 31: drip {drip_stretch}
948 32: stone {stone_pause}
949 33: bomb {bomb_pause}
950 34: diamond {diamond_pause}
951 35: emerald {emerald_pause}
952 36: wonderwall {wonderwallB}
962 46: blank {sand_stonein_2}
963 47: blank {sand_stonein_3}
964 48: blank {sand_stonein_4}
965 49: sand {sand_stonesand_2}
966 50: sand {sand_stonesand_3}
967 51: sand {sand_stonesand_4}
968 52: sand_stone {sand_sandstone_2}
969 53: sand_stone {sand_sandstone_3}
970 54: sand_stone {sand_sandstone_4}
971 55: sand {sand_stonesand_4}
972 56: stone {sand_stoneout_2}
986 70: spring {spring_fall}
987 71: spring {spring_w}
988 72: spring {spring_e}
993 77: android {android_n_1}
994 78: android {android_n_2}
995 79: android {android_s_1}
996 80: android {android_s_2}
997 81: android {android_e_1}
998 82: android {android_e_2}
999 83: android {android_w_1}
1000 84: android {android_w_2}
1015 99: spring {push_spring_w}
1016 100: spring {push_spring_e}
1025 109: pause {grass_wB}
1026 110: pause {grass_eB}
1027 111: pause {grass_nB}
1028 112: pause {grass_sB}
1029 113: pause {dynamite_blank}
1030 114: nut {push_nut_w}
1031 115: nut {push_nut_e}
1032 116: steel_2 {end of level}
1034 118: pause {emerald_blank}
1035 119: bomb {push_bomb_w}
1036 120: bomb {push_bomb_e}
1037 121: stone {push_stone_w}
1038 122: stone {push_stone_e}
1039 123: pause {diamond_blank}
1040 124: pause {dirt_wB}
1041 125: pause {dirt_eB}
1042 126: pause {dirt_nB}
1043 127: pause {dirt_sB}
1080 163: fake_blank {fake_blankB}
1081 164: fake_grass {fake_grassB}
1083 166: switch {switchB}
1174 ----------------------------------------------------------------------
1190 2091: dynamite value
1194 2095: emeralds needed
1198 2102: wonderwall time
1200 2106: ID (0xff353030)
1204 1: stone {stone_fall}
1206 3: diamond {diamond_fall}
1208 5: alien {alien_pause}
1220 17: bomb {bomb_fall}
1222 19: emerald {emerald_fall}
1232 29: drip {drip_fall}
1233 30: blank {drip_stretchB}
1234 31: drip {drip_stretch}
1235 32: stone {stone_pause}
1236 33: bomb {bomb_pause}
1237 34: diamond {diamond_pause}
1238 35: emerald {emerald_pause}
1239 36: wonderwall {wonderwallB}
1249 46: blank {sand_stonein_2}
1250 47: blank {sand_stonein_3}
1251 48: blank {sand_stonein_4}
1252 49: sand {sand_stonesand_2}
1253 50: sand {sand_stonesand_3}
1254 51: sand {sand_stonesand_4}
1255 52: sand_stone {sand_sandstone_2}
1256 53: sand_stone {sand_sandstone_3}
1257 54: sand_stone {sand_sandstone_4}
1258 55: sand {sand_stonesand_4}
1259 56: stone {sand_stoneout_2}
1312 109: pause {grass_wB}
1313 110: pause {grass_eB}
1314 111: pause {grass_nB}
1315 112: pause {grass_sB}
1316 113: pause {dynamite_blank}
1317 114: nut {push_nut_w}
1318 115: nut {push_nut_e}
1319 116: steel_2 {end of level}
1320 117: dynamite_4 {boom_2}
1321 118: pause {emerald_blank}
1322 119: bomb {push_bomb_w}
1323 120: bomb {push_bomb_e}
1324 121: stone {push_stone_w}
1325 122: stone {push_stone_e}
1326 123: pause {diamond_blank}
1327 124: pause {dirt_wB}
1328 125: pause {dirt_eB}
1329 126: pause {dirt_nB}
1330 127: pause {dirt_sB}
1461 ----------------------------------------------------------------------
1477 2091: dynamite value
1481 2095: emeralds needed
1485 2102: wonderwall time
1515 26: diamond {diamond_shine}
1516 27: emerald {emerald_shine}
1519 1: stone {stone_fall}
1521 3: diamond {diamond_fall}
1523 5: alien {alien_pause}
1535 17: bomb {bomb_fall}
1537 19: emerald {emerald_fall}
1547 29: drip {drip_fall}
1548 30: blank {drip_stretchB}
1549 31: drip {drip_stretch}
1550 32: stone {stone_pause}
1551 33: bomb {bomb_pause}
1552 34: diamond {diamond_pause}
1553 35: emerald {emerald_pause}
1554 36: wonderwall {wonderwallB}
1564 46: blank {sand_stonein_2}
1565 47: blank {sand_stonein_3}
1566 48: blank {sand_stonein_4}
1567 49: sand {sand_stonesand_2}
1568 50: sand {sand_stonesand_3}
1569 51: sand {sand_stonesand_4}
1570 52: sand_stone {sand_sandstone_2}
1571 53: sand_stone {sand_sandstone_3}
1572 54: sand_stone {sand_sandstone_4}
1573 55: sand {sand_stonesand_4}
1574 56: stone {sand_stoneout_2}
1631 113: pause {dynamite_blank}
1632 114: nut {push_nut_w}
1633 115: nut {push_nut_e}
1634 116: steel_1 {end of level}
1635 117: dynamite_4 {boom_2}
1636 118: pause {emerald_blank}
1637 119: bomb {push_bomb_w}
1638 120: bomb {push_bomb_e}
1639 121: stone {push_stone_w}
1640 122: stone {push_stone_e}
1641 123: pause {diamond_blank}
1642 124: pause {dirt_wB}
1643 125: pause {dirt_eB}
1644 126: pause {dirt_nB}
1645 127: pause {dirt_sB}
1678 159: fake_grass {dirt}
1679 160: fake_grass {dirt}
1680 161: fake_grass {dirt}
1681 162: fake_grass {dirt}
1682 163: fake_grass {dirt}
1683 164: fake_grass {dirt}
1684 165: fake_grass {dirt}
1685 166: fake_grass {dirt}
1686 167: fake_grass {dirt}
1687 168: fake_grass {dirt}
1688 169: fake_grass {dirt}
1689 170: fake_grass {dirt}
1690 171: fake_grass {dirt}
1691 172: fake_grass {dirt}
1692 173: fake_grass {dirt}
1693 174: fake_grass {dirt}
1759 240: alpha_arrow_e {}
1760 241: decor_1 {alpha_copyr}
1776 ----------------------------------------------------------------------