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 void init_android_clone_table(short android_clone_bits)
131 boolean android_emerald = (android_clone_bits & 1) != 0;
132 boolean android_diamond = (android_clone_bits & 2) != 0;
133 boolean android_stone = (android_clone_bits & 4) != 0;
134 boolean android_bomb = (android_clone_bits & 8) != 0;
135 boolean android_nut = (android_clone_bits & 16) != 0;
136 boolean android_tank = (android_clone_bits & 32) != 0;
137 boolean android_eater = (android_clone_bits & 64) != 0;
138 boolean android_bug = (android_clone_bits & 128) != 0;
139 boolean android_alien = (android_clone_bits & 256) != 0;
140 boolean android_spring = (android_clone_bits & 512) != 0;
141 boolean android_balloon = (android_clone_bits & 1024) != 0;
142 boolean android_amoeba = (android_clone_bits & 2048) != 0;
143 boolean android_dynamite = (android_clone_bits & 4096) != 0;
146 for (i = 0; i < TILE_MAX; i++)
147 cav.android_array[i] = Xblank;
151 cav.android_array[Xeater_n] = Xeater_n;
152 cav.android_array[Yeater_nB] = Xeater_n;
154 cav.android_array[Xeater_e] = Xeater_e;
155 cav.android_array[Yeater_eB] = Xeater_e;
157 cav.android_array[Xeater_s] = Xeater_s;
158 cav.android_array[Yeater_sB] = Xeater_s;
160 cav.android_array[Xeater_w] = Xeater_w;
161 cav.android_array[Yeater_wB] = Xeater_w;
166 cav.android_array[Xalien] = Xalien;
167 cav.android_array[Xalien_pause] = Xalien;
168 cav.android_array[Yalien_nB] = Xalien;
169 cav.android_array[Yalien_eB] = Xalien;
170 cav.android_array[Yalien_sB] = Xalien;
171 cav.android_array[Yalien_wB] = Xalien;
176 cav.android_array[Xbug_1_n] = Xbug_2_n;
177 cav.android_array[Xbug_2_n] = Xbug_2_n;
178 cav.android_array[Ybug_nB] = Xbug_2_n;
179 cav.android_array[Ybug_n_e] = Xbug_2_n;
180 cav.android_array[Ybug_n_w] = Xbug_2_n;
182 cav.android_array[Xbug_1_e] = Xbug_2_e;
183 cav.android_array[Xbug_2_e] = Xbug_2_e;
184 cav.android_array[Ybug_eB] = Xbug_2_e;
185 cav.android_array[Ybug_e_s] = Xbug_2_e;
186 cav.android_array[Ybug_e_n] = Xbug_2_e;
188 cav.android_array[Xbug_1_s] = Xbug_2_s;
189 cav.android_array[Xbug_2_s] = Xbug_2_s;
190 cav.android_array[Ybug_sB] = Xbug_2_s;
191 cav.android_array[Ybug_s_w] = Xbug_2_s;
192 cav.android_array[Ybug_s_e] = Xbug_2_s;
194 cav.android_array[Xbug_1_w] = Xbug_2_w;
195 cav.android_array[Xbug_2_w] = Xbug_2_w;
196 cav.android_array[Ybug_wB] = Xbug_2_w;
197 cav.android_array[Ybug_w_n] = Xbug_2_w;
198 cav.android_array[Ybug_w_s] = Xbug_2_w;
203 cav.android_array[Xtank_1_n] = Xtank_1_n;
204 cav.android_array[Xtank_2_n] = Xtank_1_n;
205 cav.android_array[Ytank_nB] = Xtank_1_n;
206 cav.android_array[Ytank_n_e] = Xtank_1_n;
207 cav.android_array[Ytank_n_w] = Xtank_1_n;
209 cav.android_array[Xtank_1_e] = Xtank_1_e;
210 cav.android_array[Xtank_2_e] = Xtank_1_e;
211 cav.android_array[Ytank_eB] = Xtank_1_e;
212 cav.android_array[Ytank_e_s] = Xtank_1_e;
213 cav.android_array[Ytank_e_n] = Xtank_1_e;
215 cav.android_array[Xtank_1_s] = Xtank_1_s;
216 cav.android_array[Xtank_2_s] = Xtank_1_s;
217 cav.android_array[Ytank_sB] = Xtank_1_s;
218 cav.android_array[Ytank_s_w] = Xtank_1_s;
219 cav.android_array[Ytank_s_e] = Xtank_1_s;
221 cav.android_array[Xtank_1_w] = Xtank_1_w;
222 cav.android_array[Xtank_2_w] = Xtank_1_w;
223 cav.android_array[Ytank_wB] = Xtank_1_w;
224 cav.android_array[Ytank_w_n] = Xtank_1_w;
225 cav.android_array[Ytank_w_s] = Xtank_1_w;
230 cav.android_array[Xemerald] = Xemerald;
231 cav.android_array[Xemerald_pause] = Xemerald;
232 cav.android_array[Xemerald_fall] = Xemerald;
233 cav.android_array[Yemerald_sB] = Xemerald;
234 cav.android_array[Yemerald_eB] = Xemerald;
235 cav.android_array[Yemerald_wB] = Xemerald;
240 cav.android_array[Xdiamond] = Xdiamond;
241 cav.android_array[Xdiamond_pause] = Xdiamond;
242 cav.android_array[Xdiamond_fall] = Xdiamond;
243 cav.android_array[Ydiamond_sB] = Xdiamond;
244 cav.android_array[Ydiamond_eB] = Xdiamond;
245 cav.android_array[Ydiamond_wB] = Xdiamond;
250 cav.android_array[Xstone] = Xstone;
251 cav.android_array[Xstone_pause] = Xstone;
252 cav.android_array[Xstone_fall] = Xstone;
253 cav.android_array[Ystone_sB] = Xstone;
254 cav.android_array[Ystone_eB] = Xstone;
255 cav.android_array[Ystone_wB] = Xstone;
260 cav.android_array[Xbomb] = Xbomb;
261 cav.android_array[Xbomb_pause] = Xbomb;
262 cav.android_array[Xbomb_fall] = Xbomb;
263 cav.android_array[Ybomb_sB] = Xbomb;
264 cav.android_array[Ybomb_eB] = Xbomb;
265 cav.android_array[Ybomb_wB] = Xbomb;
270 cav.android_array[Xnut] = Xnut;
271 cav.android_array[Xnut_pause] = Xnut;
272 cav.android_array[Xnut_fall] = Xnut;
273 cav.android_array[Ynut_sB] = Xnut;
274 cav.android_array[Ynut_eB] = Xnut;
275 cav.android_array[Ynut_wB] = Xnut;
280 cav.android_array[Xspring] = Xspring;
281 cav.android_array[Xspring_pause] = Xspring;
282 cav.android_array[Xspring_fall] = Xspring;
283 cav.android_array[Xspring_e] = Xspring;
284 cav.android_array[Xspring_w] = Xspring;
285 cav.android_array[Yspring_sB] = Xspring;
286 cav.android_array[Yspring_eB] = Xspring;
287 cav.android_array[Yspring_wB] = Xspring;
288 cav.android_array[Yspring_alien_eB] = Xspring;
289 cav.android_array[Yspring_alien_wB] = Xspring;
292 if (android_dynamite)
294 cav.android_array[Xdynamite] = Xdynamite;
299 cav.android_array[Xballoon] = Xballoon;
300 cav.android_array[Yballoon_nB] = Xballoon;
301 cav.android_array[Yballoon_eB] = Xballoon;
302 cav.android_array[Yballoon_sB] = Xballoon;
303 cav.android_array[Yballoon_wB] = Xballoon;
308 cav.android_array[Xfake_amoeba] = Xdrip;
309 cav.android_array[Yfake_amoeba] = Xdrip;
310 cav.android_array[Xamoeba_1] = Xdrip;
311 cav.android_array[Xamoeba_2] = Xdrip;
312 cav.android_array[Xamoeba_3] = Xdrip;
313 cav.android_array[Xamoeba_4] = Xdrip;
314 cav.android_array[Xamoeba_5] = Xdrip;
315 cav.android_array[Xamoeba_6] = Xdrip;
316 cav.android_array[Xamoeba_7] = Xdrip;
317 cav.android_array[Xamoeba_8] = Xdrip;
321 void convert_em_level(unsigned char *src, int file_version)
323 static int eater_offset[8] =
325 2048, 2057, 2066, 2075,
326 2112, 2121, 2130, 2139
330 /* common to all emc caves */
332 cav.time_seconds = GET_BE16(src[2110]);
333 if (cav.time_seconds > 9999)
334 cav.time_seconds = 9999;
336 cav.required = src[2095];
340 cav.emerald_score = src[2084];
341 cav.diamond_score = src[2085];
342 cav.alien_score = src[2086];
343 cav.tank_score = src[2087];
344 cav.bug_score = src[2088];
345 cav.eater_score = src[2089];
346 cav.nut_score = src[2090];
347 cav.dynamite_score = src[2091];
348 cav.key_score = src[2092];
349 cav.exit_score = src[2093] * 8 / 5;
351 cav.lenses_score = src[2151];
352 cav.magnify_score = src[2152];
353 cav.slurp_score = src[2153];
357 cav.android_move_time = GET_BE16(src[2164]);
358 cav.android_clone_time = GET_BE16(src[2166]);
359 cav.ball_time = GET_BE16(src[2160]);
361 cav.lenses_time = GET_BE16(src[2154]);
362 cav.magnify_time = GET_BE16(src[2156]);
363 cav.wheel_time = GET_BE16(src[2104]);
365 temp = GET_BE16(src[2100]) * 28;
368 cav.amoeba_time = temp;
370 cav.wonderwall_time = GET_BE16(src[2102]);
372 cav.wind_cnt = src[2149] & 15 ? cav.wind_time : 0;
374 cav.wind_direction = (temp & 8 ? 0 :
380 cav.ball_random = src[2162] & 1 ? 1 : 0;
381 cav.ball_state = src[2162] & 128 ? 1 : 0;
383 for (temp = 1; temp < 2047; temp++)
387 case 36: /* wonderwall */
388 cav.wonderwall_state = 1;
389 cav.wonderwall_time = 9999;
393 cav.wheel_x = temp & 63;
394 cav.wheel_y = temp >> 6;
395 cav.wheel_cnt = cav.wheel_time;
398 case 163: /* fake blank */
399 cav.lenses_cnt = 9999;
402 case 164: /* fake grass */
403 cav.magnify_cnt = 9999;
410 temp = GET_BE16(src[2168]);
412 init_android_clone_table(temp);
416 for (i = 0; i < 8; i++)
417 for (x = 0; x < 9; x++)
418 cav.eater_array[i][x] = map_emc[src[eater_offset[i] + x]];
422 temp = map_emc[src[2159]];
424 for (y = 0; y < 8; y++)
428 for (x = 0; x < 8; x++)
429 cav.ball_array[y][x] = temp;
433 cav.ball_array[y][1] = (src[2163] & 1) ? temp : Xblank; /* north */
434 cav.ball_array[y][6] = (src[2163] & 2) ? temp : Xblank; /* south */
435 cav.ball_array[y][3] = (src[2163] & 4) ? temp : Xblank; /* west */
436 cav.ball_array[y][4] = (src[2163] & 8) ? temp : Xblank; /* east */
437 cav.ball_array[y][7] = (src[2163] & 16) ? temp : Xblank; /* southeast */
438 cav.ball_array[y][5] = (src[2163] & 32) ? temp : Xblank; /* southwest */
439 cav.ball_array[y][2] = (src[2163] & 64) ? temp : Xblank; /* northeast */
440 cav.ball_array[y][0] = (src[2163] & 128)? temp : Xblank; /* northwest */
446 for (i = 0; i < 2; i++)
448 temp = GET_BE16(src[2096 + i * 2]);
450 cav.player_x[i] = (temp & 63);
451 cav.player_y[i] = (temp >> 6 & 31);
456 /* first fill the complete playfield with the default border element */
457 for (y = 0; y < CAVE_HEIGHT; y++)
458 for (x = 0; x < CAVE_WIDTH; x++)
459 cav.cave[x][y] = Zborder;
461 /* then copy the real level contents from level file into the playfield */
463 for (y = 0; y < cav.height; y++)
464 for (x = 0; x < cav.width; x++)
465 cav.cave[x][y] = map_emc[src[temp++]];
467 /* at last, set the two players at their positions in the playfield */
468 /* (native EM[C] levels always have exactly two players in a level) */
469 for (i = 0; i < 2; i++)
470 cav.cave[cav.player_x[i]][cav.player_y[i]] = Zplayer;
472 native_em_level.file_version = file_version;
476 /* convert all emerald mine caves to emc version 6 cave format.
478 * caves are filtered to get rid of invalid or unsupported tiles.
480 * although the result is a somewhat clean cave, it is meant only
481 * to give a common structure for the binary cave format. it is not
482 * for archiving purposes (it is better to keep the raw cave as-is)
483 * and it is not meant for serializing (the intermediate structure
484 * is better defined).
486 * acid top is added to acid bottom in both the cave and the eaters.
487 * fake acid (only in v4) does not exist because it adds nothing to
488 * the game, and is different even in different versions of the emc
491 * v4/v5 time is converted to 10x old time (as it should be).
492 * the reason the kingsoft player used 5x time was copy protection.
494 * note: emc v6 converter has an error in converting v4 eaters to the
495 * wrong bug(24 instead of 20) and tank(12 instead of 8).
498 /* changes for game engine integration in Rocks'n'Diamonds:
500 * cave versions below V5 had no grass, but only sand/dirt
501 * - object code 130 (V6 grass) is changed to 189 (V6 dirt)
502 * - object codes are changed in both cave and eater arrays
503 * - only graphical change, as both objects behave the same
506 static const unsigned char map_v6[256] =
510 0,0,2,2, 4,4,118,118, 8,9,10,11, 12,13,14,15,
511 16,16,18,18, 20,21,22,23, 24,25,26,27, 28,28,118,28,
512 0,16,2,18, 36,37,37,37, 40,41,42,43, 44,45,128,128,
513 128,148,148, 148,45,45,45, 148,0,57,58, 59,60,61,62,63,
515 64,65,66,67, 68,69,69,71, 72,73,74,75, 118,75,75,75,
516 75,75,75,75, 75,153,153,153, 153,153,153,153, 153,153,153,153,
517 153,153,153,99, 100,68,68,68, 68,68,68,68, 68,118,118,118,
518 118,118,114,115, 131,118,118,119, 120,121,122,118, 118,118,118,118,
520 128,129,130,131, 132,133,134,135, 136,137,138,139, 140,141,142,143,
521 144,145,146,147, 148,149,150,151, 152,153,154,155, 156,157,158,159,
522 160,161,162,163, 164,165,165,118, 168,169,170,171, 172,173,174,175,
523 176,177,178,179, 180,181,182,183, 184,185,186,187, 188,189,68,191,
525 192,193,194,195, 196,197,198,199, 200,201,202,203, 204,205,206,207,
526 208,209,210,211, 212,213,214,215, 216,217,218,219, 220,221,222,223,
527 224,225,226,227, 228,229,230,231, 232,233,234,235, 236,237,238,239,
528 240,241,242,243, 244,245,153,153, 153,153,153,153, 153,153,153,153
531 static const unsigned char map_v5[256] =
535 0,0,2,2, 4,4,118,118, 8,9,10,11, 12,13,14,15,
536 16,16,18,18, 20,21,22,23, 24,25,26,27, 28,28,118,28,
537 0,16,2,18, 36,37,37,37, 147,41,42,43, 44,45,128,128,
538 128,148,148,148, 45,45,45,148, 0,57,58,59, 60,61,62,63,
540 64,65,66,67, 68,153,153,153, 153,153,153,153, 153,153,153,153,
541 153,153,153,153, 153,153,153,153, 153,153,153,153, 153,153,153,153,
542 153,153,153,153, 153,68,68,68, 68,68,68,68, 68,118,118,118,
543 118,118,114,115, 131,118,118,119, 120,121,122,118, 118,118,118,118,
545 128,129,130,131, 132,133,134,135, 136,137,138,139, 140,141,142,143,
546 144,145,146,147, 148,149,150,151, 152,153,154,155, 156,157,158,159,
547 160,153,153,153, 153,153,153,118, 168,169,170,171, 172,173,174,175,
548 176,177,178,179, 180,181,182,183, 184,185,186,187, 188,189,68,153,
550 153,153,153,153, 153,153,153,153, 200,201,202,203, 204,205,206,207,
551 208,209,210,211, 212,213,214,215, 216,217,218,219, 220,221,222,223,
552 224,225,226,227, 228,229,230,231, 232,233,234,235, 236,237,238,239,
553 240,241,153,153, 153,153,153,153, 153,153,153,153, 153,153,153,153
556 static const unsigned char map_v4[256] =
560 0,0,2,2, 4,4,118,118, 8,9,10,11, 12,13,14,15,
561 16,16,18,18, 20,21,22,23, 24,25,26,27, 28,28,118,28,
562 0,16,2,18, 36,37,37,37, 147,41,42,43, 44,45,128,128,
563 128,148,148,148, 45,45,45,148, 0,153,153,59, 60,61,62,63,
565 64,65,66,153, 153,153,153,153, 153,153,153,153, 153,153,153,153,
566 153,153,153,153, 153,153,153,153, 153,153,153,153, 153,153,153,153,
567 153,153,153,153, 153,153,153,153, 153,153,153,153, 153,153,153,153,
568 153,118,114,115, 131,118,118,119, 120,121,122,118, 118,118,118,118,
570 128,129,189,131, 132,133,134,135, 136,137,138,139, 140,141,142,143,
571 144,145,146,147, 148,149,150,151, 152,68,154,155, 156,157,158,160,
572 160,160,160,160, 160,160,160,160, 160,160,160,160, 160,160,160,175,
573 153,153,153,153, 153,153,153,153, 153,153,153,153, 153,153,68,153,
575 153,153,153,153, 153,153,153,153, 200,201,202,203, 204,205,206,207,
576 208,209,210,211, 212,213,214,215, 216,217,218,219, 220,221,222,223,
577 224,225,226,227, 228,229,230,231, 232,233,234,235, 236,237,238,239,
578 240,241,153,153, 153,153,153,153, 153,153,153,153, 153,153,153,153
581 static const unsigned char map_v4_eater[32] =
583 /* filter for v4 eater */
585 128,18,2,0, 4,8,16,20, 28,37,41,45, 189,129,131,132,
586 133,134,135,136, 146,147,175,65, 66,64,2,18, 128,128,128,128
589 static boolean filename_has_v1_format(char *filename)
591 char *basename = getBaseNamePtr(filename);
593 return (strlen(basename) == 3 &&
594 basename[0] == 'a' &&
595 basename[1] >= 'a' && basename[1] <= 'k' &&
596 basename[2] >= '0' && basename[2] <= '9');
599 int cleanup_em_level(unsigned char *src, int length, char *filename)
601 int file_version = FILE_VERSION_EM_UNKNOWN;
604 if (length >= 2172 &&
605 src[2106] == 255 && /* version id: */
606 src[2107] == 54 && /* '6' */
607 src[2108] == 48 && /* '0' */
608 src[2109] == 48) /* '0' */
610 /* ---------- this cave has V6 file format ---------- */
611 file_version = FILE_VERSION_EM_V6;
613 /* remap elements to internal EMC level format */
614 for (i = 0; i < 2048; i++)
615 src[i] = map_v6[src[i]];
616 for (i = 2048; i < 2084; i++)
617 src[i] = map_v6[src[i]];
618 for (i = 2112; i < 2148; i++)
619 src[i] = map_v6[src[i]];
621 else if (length >= 2110 &&
622 src[2106] == 255 && /* version id: */
623 src[2107] == 53 && /* '5' */
624 src[2108] == 48 && /* '0' */
625 src[2109] == 48) /* '0' */
627 /* ---------- this cave has V5 file format ---------- */
628 file_version = FILE_VERSION_EM_V5;
630 /* remap elements to internal EMC level format */
631 for (i = 0; i < 2048; i++)
632 src[i] = map_v5[src[i]];
633 for (i = 2048; i < 2084; i++)
634 src[i] = map_v5[src[i]];
635 for (i = 2112; i < 2148; i++)
636 src[i] = src[i - 64];
638 else if (length >= 2106 &&
639 (src[1983] == 27 || /* encrypted (only EM I/II/III) */
640 src[1983] == 116 || /* unencrypted (usual case) */
641 src[1983] == 131)) /* unencrypted (rare case) */
643 /* ---------- this cave has V1, V2 or V3 file format ---------- */
645 boolean fix_copyright = FALSE;
648 byte at position 1983 (0x07bf) is used as "magic byte":
649 - 27 (0x1b) => encrypted level (V3 only / Kingsoft original games)
650 - 116 (0x74) => unencrypted level (byte is corrected to 131 (0x83))
651 - 131 (0x83) => unencrypted level (happens only in very rare cases)
654 if (src[1983] == 27) /* (0x1b) -- after decryption: 116 (0x74) */
656 /* this is original (encrypted) Emerald Mine I, II or III level file */
658 int first_byte = src[0];
659 unsigned char code0 = 0x65;
660 unsigned char code1 = 0x11;
662 /* decode encrypted level data */
663 for (i = 0; i < 2106; i++)
668 code0 = (code0 + 7) & 0xff;
671 src[1] = 131; /* needed for all Emerald Mine levels */
673 /* first byte is either 0xf1 (EM I and III) or 0xf5 (EM II) */
674 if (first_byte == 0xf5)
676 src[0] = 131; /* only needed for Emerald Mine II levels */
678 fix_copyright = TRUE;
681 /* ---------- this cave has V3 file format ---------- */
682 file_version = FILE_VERSION_EM_V3;
684 else if (filename_has_v1_format(filename))
686 /* ---------- this cave has V1 file format ---------- */
687 file_version = FILE_VERSION_EM_V1;
691 /* ---------- this cave has V2 file format ---------- */
692 file_version = FILE_VERSION_EM_V2;
695 /* remap elements to internal EMC level format */
696 for (i = 0; i < 2048; i++)
697 src[i] = map_v4[src[i]];
698 for (i = 2048; i < 2084; i++)
699 src[i] = map_v4_eater[src[i] >= 28 ? 0 : src[i]];
700 for (i = 2112; i < 2148; i++)
701 src[i] = src[i - 64];
703 if (fix_copyright) /* fix "(c)" sign in Emerald Mine II levels */
705 for (i = 0; i < 2048; i++)
707 src[i] = 254; /* replace 'Xdecor_1' with 'Xalpha_copyr' */
712 /* ---------- this cave has unknown file format ---------- */
714 /* if file has length of old-style level file, print (wrong) magic byte */
716 Error(ERR_WARN, "unknown magic byte 0x%02x at position 0x%04x",
719 return FILE_VERSION_EM_UNKNOWN;
722 if (file_version < FILE_VERSION_EM_V6)
725 src[2106] = 255; /* version id: */
726 src[2107] = 54; /* '6' */
727 src[2108] = 48; /* '0' */
728 src[2109] = 48; /* '0' */
732 /* stored level time of levels for the V2 player was changed to 50% of the
733 time for the V1 player (original V3 levels already considered this) */
734 if (file_version != FILE_VERSION_EM_V1 &&
735 file_version != FILE_VERSION_EM_V3)
740 for (i = 2148; i < 2172; i++)
747 /* ---------- at this stage, the cave data always has V6 format ---------- */
750 for (i = 0; i < 2048; i++)
753 for (i++; i < 2048; i++)
758 for (i = 64; i < 2048; i++)
759 if (src[i] == 63) /* replace element above 'Xacid_s' ... */
760 src[i - 64] = 101; /* ... with 'Xacid_1' */
762 /* fix acid with no base beneath it (see below for details (*)) */
763 for (i = 64; i < 2048 - 1; i++)
765 if (file_version <= FILE_VERSION_EM_V2 &&
766 src[i - 64] == 101 && src[i] != 63) /* acid without base */
768 if (src[i - 1] == 101 || /* remove acid over acid row */
770 src[i - 64] = 6; /* replace element above with 'Xblank' */
772 src[i - 64] = 255; /* replace element above with 'Xfake_acid_1' */
776 /* fix acid in eater 1 */
777 for (i = 2051; i < 2057; i++)
781 /* fix acid in eater 2 */
782 for (i = 2060; i < 2066; i++)
786 /* fix acid in eater 3 */
787 for (i = 2069; i < 2075; i++)
791 /* fix acid in eater 4 */
792 for (i = 2078; i < 2084; i++)
796 /* fix acid in eater 5 */
797 for (i = 2115; i < 2121; i++)
801 /* fix acid in eater 6 */
802 for (i = 2124; i < 2130; i++)
806 /* fix acid in eater 7 */
807 for (i = 2133; i < 2139; i++)
811 /* fix acid in eater 8 */
812 for (i = 2142; i < 2148; i++)
821 src[GET_BE16(src[2096])] = 128;
825 src[GET_BE16(src[2098])] = 128;
828 if (GET_BE16(src[2100]) > 9999)
829 PUT_BE16(src[2100], 9999);
831 /* time wonderwall */
832 if (GET_BE16(src[2102]) > 9999)
833 PUT_BE16(src[2102], 9999);
836 if (GET_BE16(src[2110]) > 9999)
837 PUT_BE16(src[2110], 9999);
846 if (GET_BE16(src[2154]) > 9999)
847 PUT_BE16(src[2154], 9999);
850 if (GET_BE16(src[2156]) > 9999)
851 PUT_BE16(src[2156], 9999);
855 src[2159] = map_v6[src[2159]];
858 if (GET_BE16(src[2160]) > 9999)
859 PUT_BE16(src[2160], 9999);
866 /* android move pause */
867 if (GET_BE16(src[2164]) > 9999)
868 PUT_BE16(src[2164], 9999);
870 /* android clone pause */
871 if (GET_BE16(src[2166]) > 9999)
872 PUT_BE16(src[2166], 9999);
877 /* size of v6 cave */
881 Error(ERR_DEBUG, "EM level file version: %d", file_version);
890 structure of emerald mine level disk files
891 ----------------------------------------------------------------------
893 if(len >= 2172 && (buf[2106] == 255 && buf[2107] == 54 && buf[2108] == 48 && buf[2109] == 48)) // v6
894 if(len >= 2110 && (buf[2106] == 255 && buf[2107] == 53 && buf[2108] == 48 && buf[2109] == 48)) // v5
895 if(len >= 2106 && (buf[1983] == 116 || buf[2047] == 116)) // v4
896 if(len >= 2106 && (buf[1983] == 27 || buf[2047] == 219)) // v3
898 buf[0]=241;buf[1]=248;for(i=0,j=101;i<2106;i++,j+=7)buf[i]=(buf[i]^j)-17; // decrypt
900 number of movements (calls to logic) = time * 50 / 8
902 {} reserved (but some broken levels use them)
904 ----------------------------------------------------------------------
924 2095: emeralds needed
928 2102: wonderwall time
930 2106: ID (0xff363030)
936 2148: flags bit#7=NOI #6=RIS
937 2149: wind direction bit#0=right #1=down #2=left #3=up
938 2150: cave number bit#7=teamwork
947 2162: ball info bit#15=switch state #8=random
948 ; bit#0=N #1=S #2=W #3=E #4=SE #5=SW #6=NE #7=NW
949 2164: android move speed
950 2166: android clone speed
952 ; bit#0=emerald #1=diamond #2=stone #3=bomb #4=nut #5=tank #6=eater
953 ; #7=bug #8=alien #9=spring #10=balloon #11=ameuba #12=dynamite
958 1: stone {stone_fall}
960 3: diamond {diamond_fall}
962 5: alien {alien_pause}
976 19: emerald {emerald_fall}
987 30: blank {drip_stretchB}
988 31: drip {drip_stretch}
989 32: stone {stone_pause}
990 33: bomb {bomb_pause}
991 34: diamond {diamond_pause}
992 35: emerald {emerald_pause}
993 36: wonderwall {wonderwallB}
1003 46: blank {sand_stonein_2}
1004 47: blank {sand_stonein_3}
1005 48: blank {sand_stonein_4}
1006 49: sand {sand_stonesand_2}
1007 50: sand {sand_stonesand_3}
1008 51: sand {sand_stonesand_4}
1009 52: sand_stone {sand_sandstone_2}
1010 53: sand_stone {sand_sandstone_3}
1011 54: sand_stone {sand_sandstone_4}
1012 55: sand {sand_stonesand_4}
1013 56: stone {sand_stoneout_2}
1027 70: spring {spring_fall}
1028 71: spring {spring_w}
1029 72: spring {spring_e}
1034 77: android {android_n_1}
1035 78: android {android_n_2}
1036 79: android {android_s_1}
1037 80: android {android_s_2}
1038 81: android {android_e_1}
1039 82: android {android_e_2}
1040 83: android {android_w_1}
1041 84: android {android_w_2}
1056 99: spring {push_spring_w}
1057 100: spring {push_spring_e}
1066 109: pause {grass_wB}
1067 110: pause {grass_eB}
1068 111: pause {grass_nB}
1069 112: pause {grass_sB}
1070 113: pause {dynamite_blank}
1071 114: nut {push_nut_w}
1072 115: nut {push_nut_e}
1073 116: steel_2 {end of level}
1075 118: pause {emerald_blank}
1076 119: bomb {push_bomb_w}
1077 120: bomb {push_bomb_e}
1078 121: stone {push_stone_w}
1079 122: stone {push_stone_e}
1080 123: pause {diamond_blank}
1081 124: pause {dirt_wB}
1082 125: pause {dirt_eB}
1083 126: pause {dirt_nB}
1084 127: pause {dirt_sB}
1121 163: fake_blank {fake_blankB}
1122 164: fake_grass {fake_grassB}
1124 166: switch {switchB}
1215 ----------------------------------------------------------------------
1231 2091: dynamite value
1235 2095: emeralds needed
1239 2102: wonderwall time
1241 2106: ID (0xff353030)
1245 1: stone {stone_fall}
1247 3: diamond {diamond_fall}
1249 5: alien {alien_pause}
1261 17: bomb {bomb_fall}
1263 19: emerald {emerald_fall}
1273 29: drip {drip_fall}
1274 30: blank {drip_stretchB}
1275 31: drip {drip_stretch}
1276 32: stone {stone_pause}
1277 33: bomb {bomb_pause}
1278 34: diamond {diamond_pause}
1279 35: emerald {emerald_pause}
1280 36: wonderwall {wonderwallB}
1290 46: blank {sand_stonein_2}
1291 47: blank {sand_stonein_3}
1292 48: blank {sand_stonein_4}
1293 49: sand {sand_stonesand_2}
1294 50: sand {sand_stonesand_3}
1295 51: sand {sand_stonesand_4}
1296 52: sand_stone {sand_sandstone_2}
1297 53: sand_stone {sand_sandstone_3}
1298 54: sand_stone {sand_sandstone_4}
1299 55: sand {sand_stonesand_4}
1300 56: stone {sand_stoneout_2}
1353 109: pause {grass_wB}
1354 110: pause {grass_eB}
1355 111: pause {grass_nB}
1356 112: pause {grass_sB}
1357 113: pause {dynamite_blank}
1358 114: nut {push_nut_w}
1359 115: nut {push_nut_e}
1360 116: steel_2 {end of level}
1361 117: dynamite_4 {boom_2}
1362 118: pause {emerald_blank}
1363 119: bomb {push_bomb_w}
1364 120: bomb {push_bomb_e}
1365 121: stone {push_stone_w}
1366 122: stone {push_stone_e}
1367 123: pause {diamond_blank}
1368 124: pause {dirt_wB}
1369 125: pause {dirt_eB}
1370 126: pause {dirt_nB}
1371 127: pause {dirt_sB}
1502 ----------------------------------------------------------------------
1518 2091: dynamite value
1522 2095: emeralds needed
1526 2102: wonderwall time
1556 26: diamond {diamond_shine}
1557 27: emerald {emerald_shine}
1560 1: stone {stone_fall}
1562 3: diamond {diamond_fall}
1564 5: alien {alien_pause}
1576 17: bomb {bomb_fall}
1578 19: emerald {emerald_fall}
1588 29: drip {drip_fall}
1589 30: blank {drip_stretchB}
1590 31: drip {drip_stretch}
1591 32: stone {stone_pause}
1592 33: bomb {bomb_pause}
1593 34: diamond {diamond_pause}
1594 35: emerald {emerald_pause}
1595 36: wonderwall {wonderwallB}
1605 46: blank {sand_stonein_2}
1606 47: blank {sand_stonein_3}
1607 48: blank {sand_stonein_4}
1608 49: sand {sand_stonesand_2}
1609 50: sand {sand_stonesand_3}
1610 51: sand {sand_stonesand_4}
1611 52: sand_stone {sand_sandstone_2}
1612 53: sand_stone {sand_sandstone_3}
1613 54: sand_stone {sand_sandstone_4}
1614 55: sand {sand_stonesand_4}
1615 56: stone {sand_stoneout_2}
1672 113: pause {dynamite_blank}
1673 114: nut {push_nut_w}
1674 115: nut {push_nut_e}
1675 116: steel_1 {end of level}
1676 117: dynamite_4 {boom_2}
1677 118: pause {emerald_blank}
1678 119: bomb {push_bomb_w}
1679 120: bomb {push_bomb_e}
1680 121: stone {push_stone_w}
1681 122: stone {push_stone_e}
1682 123: pause {diamond_blank}
1683 124: pause {dirt_wB}
1684 125: pause {dirt_eB}
1685 126: pause {dirt_nB}
1686 127: pause {dirt_sB}
1719 159: fake_grass {dirt}
1720 160: fake_grass {dirt}
1721 161: fake_grass {dirt}
1722 162: fake_grass {dirt}
1723 163: fake_grass {dirt}
1724 164: fake_grass {dirt}
1725 165: fake_grass {dirt}
1726 166: fake_grass {dirt}
1727 167: fake_grass {dirt}
1728 168: fake_grass {dirt}
1729 169: fake_grass {dirt}
1730 170: fake_grass {dirt}
1731 171: fake_grass {dirt}
1732 172: fake_grass {dirt}
1733 173: fake_grass {dirt}
1734 174: fake_grass {dirt}
1800 240: alpha_arrow_e {}
1801 241: decor_1 {alpha_copyr}
1817 ----------------------------------------------------------------------