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 Cstone, Cstone, Cdiamond, Cdiamond,
48 Calien, Calien, Cblank, Cblank,
49 Ctank_1_n, Ctank_1_e, Ctank_1_s, Ctank_1_w,
50 Ctank_2_n, Ctank_2_e, Ctank_2_s, Ctank_2_w,
52 Cbomb, Cbomb, Cemerald, Cemerald,
53 Cbug_1_n, Cbug_1_e, Cbug_1_s, Cbug_1_w,
54 Cbug_2_n, Cbug_2_e, Cbug_2_s, Cbug_2_w,
55 Cdrip, Cdrip, Cdrip, Cdrip,
57 Cstone, Cbomb, Cdiamond, Cemerald,
58 Cwonderwall, Cnut, Cnut, Cnut,
59 Cwheel, Ceater_n, Ceater_s, Ceater_w,
60 Ceater_e, Csand_stone, Cblank, Cblank,
62 Cblank, Csand, Csand, Csand,
63 Csand_stone, Csand_stone, Csand_stone, Csand,
64 Cstone, Cslide_ew, Cslide_ns, Cdynamite_1,
65 Cdynamite_2, Cdynamite_3, Cdynamite_4, Cacid_s,
67 Cexit_1, Cexit_2, Cexit_3, Cballoon,
68 Cplant, Cspring, Cspring, Cpush_spring_w,
69 Cpush_spring_e, Cball_1, Cball_2, Candroid,
70 Cblank, Candroid, Candroid, Candroid,
72 Candroid, Candroid, Candroid, Candroid,
73 Candroid, Cblank, Cblank, Cblank,
74 Cblank, Cblank, Cblank, Cblank,
75 Cblank, Cblank, Cblank, Cblank,
77 Cblank, Cblank, Cblank, Cpush_spring_w,
78 Cpush_spring_e, Cacid_1, Cacid_2, Cacid_3,
79 Cacid_4, Cacid_5, Cacid_6, Cacid_7,
80 Cacid_8, Cblank, Cblank, Cblank,
82 Cblank, Cblank, Cpush_nut_w, Cpush_nut_e,
83 Csteel_1, Cblank, Cblank, Cpush_bomb_w,
84 Cpush_bomb_e, Cpush_stone_w, Cpush_stone_e, Cblank,
85 Cblank, Cblank, Cblank, Cblank,
87 Cblank, Croundwall_1, Cgrass, Csteel_1,
88 Cwall_1, Ckey_1, Ckey_2, Ckey_3,
89 Ckey_4, Cdoor_1, Cdoor_2, Cdoor_3,
90 Cdoor_4, Cfake_amoeba, Cfake_door_1, Cfake_door_2,
92 Cfake_door_3, Cfake_door_4, Cwonderwall, Cwheel,
93 Csand, Cacid_nw, Cacid_ne, Cacid_sw,
94 Cacid_se, Cfake_blank, Camoeba_1, Camoeba_2,
95 Camoeba_3, Camoeba_4, Cexit, Calpha_arrow_w,
97 Cfake_grass, Clenses, Cmagnify, Cfake_blank,
98 Cfake_grass, Cswitch, Cswitch, Cblank,
99 Cdecor_8, Cdecor_9, Cdecor_10, Cdecor_5,
100 Calpha_comma, Calpha_apost, Calpha_minus, Cdynamite,
102 Csteel_3, Cdecor_6, Cdecor_7, Csteel_2,
103 Croundwall_2, Cdecor_2, Cdecor_4, Cdecor_3,
104 Cwind_any, Cwind_e, Cwind_s, Cwind_w,
105 Cwind_n, Cdirt, Cplant, Ckey_5,
107 Ckey_6, Ckey_7, Ckey_8, Cdoor_5,
108 Cdoor_6, Cdoor_7, Cdoor_8, Cbumper,
109 Calpha_a, Calpha_b, Calpha_c, Calpha_d,
110 Calpha_e, Calpha_f, Calpha_g, Calpha_h,
112 Calpha_i, Calpha_j, Calpha_k, Calpha_l,
113 Calpha_m, Calpha_n, Calpha_o, Calpha_p,
114 Calpha_q, Calpha_r, Calpha_s, Calpha_t,
115 Calpha_u, Calpha_v, Calpha_w, Calpha_x,
117 Calpha_y, Calpha_z, Calpha_0, Calpha_1,
118 Calpha_2, Calpha_3, Calpha_4, Calpha_5,
119 Calpha_6, Calpha_7, Calpha_8, Calpha_9,
120 Calpha_perio, Calpha_excla, Calpha_colon, Calpha_quest,
122 Calpha_arrow_e, Cdecor_1, Cfake_door_5, Cfake_door_6,
123 Cfake_door_7, Cfake_door_8, Cblank, Cblank,
124 Cblank, Cblank, Cblank, Cblank,
125 Cblank, Cblank, Calpha_copyr, Cfake_acid_1
134 android_clone_table[] =
136 { 0, Xemerald, Cemerald },
137 { 0, Xemerald_pause, Cemerald },
138 { 0, Xemerald_fall, Cemerald },
139 { 0, Yemerald_sB, Cemerald },
140 { 0, Yemerald_eB, Cemerald },
141 { 0, Yemerald_wB, Cemerald },
143 { 1, Xdiamond, Cdiamond },
144 { 1, Xdiamond_pause, Cdiamond },
145 { 1, Xdiamond_fall, Cdiamond },
146 { 1, Ydiamond_sB, Cdiamond },
147 { 1, Ydiamond_eB, Cdiamond },
148 { 1, Ydiamond_wB, Cdiamond },
150 { 2, Xstone, Cstone },
151 { 2, Xstone_pause, Cstone },
152 { 2, Xstone_fall, Cstone },
153 { 2, Ystone_sB, Cstone },
154 { 2, Ystone_eB, Cstone },
155 { 2, Ystone_wB, Cstone },
158 { 3, Xbomb_pause, Cbomb },
159 { 3, Xbomb_fall, Cbomb },
160 { 3, Ybomb_sB, Cbomb },
161 { 3, Ybomb_eB, Cbomb },
162 { 3, Ybomb_wB, Cbomb },
165 { 4, Xnut_pause, Cnut },
166 { 4, Xnut_fall, Cnut },
167 { 4, Ynut_sB, Cnut },
168 { 4, Ynut_eB, Cnut },
169 { 4, Ynut_wB, Cnut },
171 { 5, Xtank_1_n, Ctank_1_n },
172 { 5, Xtank_2_n, Ctank_1_n },
173 { 5, Ytank_nB, Ctank_1_n },
174 { 5, Ytank_n_e, Ctank_1_n },
175 { 5, Ytank_n_w, Ctank_1_n },
176 { 5, Xtank_1_e, Ctank_1_e },
177 { 5, Xtank_2_e, Ctank_1_e },
178 { 5, Ytank_eB, Ctank_1_e },
179 { 5, Ytank_e_s, Ctank_1_e },
180 { 5, Ytank_e_n, Ctank_1_e },
181 { 5, Xtank_1_s, Ctank_1_s },
182 { 5, Xtank_2_s, Ctank_1_s },
183 { 5, Ytank_sB, Ctank_1_s },
184 { 5, Ytank_s_w, Ctank_1_s },
185 { 5, Ytank_s_e, Ctank_1_s },
186 { 5, Xtank_1_w, Ctank_1_w },
187 { 5, Xtank_2_w, Ctank_1_w },
188 { 5, Ytank_wB, Ctank_1_w },
189 { 5, Ytank_w_n, Ctank_1_w },
190 { 5, Ytank_w_s, Ctank_1_w },
192 { 6, Xeater_n, Ceater_n },
193 { 6, Yeater_nB, Ceater_n },
194 { 6, Xeater_e, Ceater_e },
195 { 6, Yeater_eB, Ceater_e },
196 { 6, Xeater_s, Ceater_s },
197 { 6, Yeater_sB, Ceater_s },
198 { 6, Xeater_w, Ceater_w },
199 { 6, Yeater_wB, Ceater_w },
201 { 7, Xbug_1_n, Cbug_2_n },
202 { 7, Xbug_2_n, Cbug_2_n },
203 { 7, Ybug_nB, Cbug_2_n },
204 { 7, Ybug_n_e, Cbug_2_n },
205 { 7, Ybug_n_w, Cbug_2_n },
206 { 7, Xbug_1_e, Cbug_2_e },
207 { 7, Xbug_2_e, Cbug_2_e },
208 { 7, Ybug_eB, Cbug_2_e },
209 { 7, Ybug_e_s, Cbug_2_e },
210 { 7, Ybug_e_n, Cbug_2_e },
211 { 7, Xbug_1_s, Cbug_2_s },
212 { 7, Xbug_2_s, Cbug_2_s },
213 { 7, Ybug_sB, Cbug_2_s },
214 { 7, Ybug_s_w, Cbug_2_s },
215 { 7, Ybug_s_e, Cbug_2_s },
216 { 7, Xbug_1_w, Cbug_2_w },
217 { 7, Xbug_2_w, Cbug_2_w },
218 { 7, Ybug_wB, Cbug_2_w },
219 { 7, Ybug_w_n, Cbug_2_w },
220 { 7, Ybug_w_s, Cbug_2_w },
222 { 8, Xalien, Calien },
223 { 8, Xalien_pause, Calien },
224 { 8, Yalien_nB, Calien },
225 { 8, Yalien_eB, Calien },
226 { 8, Yalien_sB, Calien },
227 { 8, Yalien_wB, Calien },
229 { 9, Xspring, Cspring },
230 { 9, Xspring_pause, Cspring },
231 { 9, Xspring_fall, Cspring },
232 { 9, Xspring_e, Cspring },
233 { 9, Xspring_w, Cspring },
234 { 9, Yspring_sB, Cspring },
235 { 9, Yspring_eB, Cspring },
236 { 9, Yspring_wB, Cspring },
237 { 9, Yspring_alien_eB, Cspring },
238 { 9, Yspring_alien_wB, Cspring },
240 { 10, Xballoon, Cballoon },
241 { 10, Yballoon_nB, Cballoon },
242 { 10, Yballoon_eB, Cballoon },
243 { 10, Yballoon_sB, Cballoon },
244 { 10, Yballoon_wB, Cballoon },
246 { 11, Xfake_amoeba, Cdrip },
247 { 11, Yfake_amoeba, Cdrip },
248 { 11, Xamoeba_1, Cdrip },
249 { 11, Xamoeba_2, Cdrip },
250 { 11, Xamoeba_3, Cdrip },
251 { 11, Xamoeba_4, Cdrip },
252 { 11, Xamoeba_5, Cdrip },
253 { 11, Xamoeba_6, Cdrip },
254 { 11, Xamoeba_7, Cdrip },
255 { 11, Xamoeba_8, Cdrip },
257 { 12, Xdynamite, Cdynamite },
262 void convert_em_level(unsigned char *src, int file_version)
264 static int eater_offset[8] =
266 2048, 2057, 2066, 2075,
267 2112, 2121, 2130, 2139
271 /* common to all emc caves */
273 cav.time_seconds = MIN(GET_BE16(src[2110]), 9999);
274 cav.gems_needed = src[2095];
277 cav.testmode = FALSE;
278 cav.teamwork = (src[2150] & 128) ? TRUE : FALSE;
282 cav.emerald_score = src[2084];
283 cav.diamond_score = src[2085];
284 cav.alien_score = src[2086];
285 cav.tank_score = src[2087];
286 cav.bug_score = src[2088];
287 cav.eater_score = src[2089];
288 cav.nut_score = src[2090];
289 cav.dynamite_score = src[2091];
290 cav.key_score = src[2092];
291 cav.exit_score = src[2093] * 8 / 5;
293 cav.lenses_score = src[2151];
294 cav.magnify_score = src[2152];
295 cav.slurp_score = src[2153];
299 cav.android_move_time = MIN(GET_BE16(src[2164]), 9999);
300 cav.android_clone_time = MIN(GET_BE16(src[2166]), 9999);
301 cav.ball_time = MIN(GET_BE16(src[2160]), 9999);
303 cav.lenses_time = MIN(GET_BE16(src[2154]), 9999);
304 cav.magnify_time = MIN(GET_BE16(src[2156]), 9999);
305 cav.wheel_time = MIN(GET_BE16(src[2104]), 9999);
307 cav.amoeba_time = MIN(GET_BE16(src[2100]) * 28, 9999);
308 cav.wonderwall_time = MIN(GET_BE16(src[2102]), 9999);
310 cav.wind_cnt = src[2149] & 15 ? cav.wind_time : 0;
312 cav.wind_direction = (temp & 8 ? 0 :
319 cav.ball_random = src[2162] & 1 ? 1 : 0;
320 cav.ball_state = src[2162] & 128 ? 1 : 0;
322 for (temp = 1; temp < 2047; temp++)
326 case 36: /* wonderwall */
327 cav.wonderwall_state = 1;
328 cav.wonderwall_time = 9999;
332 cav.wheel_x = temp & 63;
333 cav.wheel_y = temp >> 6;
334 cav.wheel_cnt = cav.wheel_time;
337 case 163: /* fake blank */
338 cav.lenses_cnt = 9999;
341 case 164: /* fake grass */
342 cav.magnify_cnt = 9999;
349 temp = GET_BE16(src[2168]);
351 for (i = 0; i < GAME_TILE_MAX; i++)
352 cav.android_array[i] = Cblank;
354 for (i = 0; android_clone_table[i].bit_nr != -1; i++)
355 if (temp & (1 << android_clone_table[i].bit_nr))
356 cav.android_array[android_clone_table[i].clone_from] =
357 android_clone_table[i].clone_to;
361 for (i = 0; i < 8; i++)
362 for (x = 0; x < 9; x++)
363 cav.eater_array[i][x] = map_emc[src[eater_offset[i] + x]];
367 temp = map_emc[src[2159]];
369 for (y = 0; y < 8; y++)
373 for (x = 0; x < 8; x++)
374 cav.ball_array[y][x] = temp;
378 cav.ball_array[y][1] = (src[2163] & 1) ? temp : Cblank; /* north */
379 cav.ball_array[y][6] = (src[2163] & 2) ? temp : Cblank; /* south */
380 cav.ball_array[y][3] = (src[2163] & 4) ? temp : Cblank; /* west */
381 cav.ball_array[y][4] = (src[2163] & 8) ? temp : Cblank; /* east */
382 cav.ball_array[y][7] = (src[2163] & 16) ? temp : Cblank; /* southeast */
383 cav.ball_array[y][5] = (src[2163] & 32) ? temp : Cblank; /* southwest */
384 cav.ball_array[y][2] = (src[2163] & 64) ? temp : Cblank; /* northeast */
385 cav.ball_array[y][0] = (src[2163] & 128)? temp : Cblank; /* northwest */
391 for (i = 0; i < 2; i++)
393 temp = GET_BE16(src[2096 + i * 2]);
395 cav.player_x[i] = (temp & 63);
396 cav.player_y[i] = (temp >> 6 & 31);
401 /* first fill the complete playfield with the empty space element */
402 for (y = 0; y < CAVE_HEIGHT; y++)
403 for (x = 0; x < CAVE_WIDTH; x++)
404 cav.cave[x][y] = Cblank;
406 /* then copy the real level contents from level file into the playfield */
408 for (y = 0; y < cav.height; y++)
409 for (x = 0; x < cav.width; x++)
410 cav.cave[x][y] = map_emc[src[temp++]];
412 native_em_level.file_version = file_version;
416 /* convert all emerald mine caves to emc version 6 cave format.
418 * caves are filtered to get rid of invalid or unsupported tiles.
420 * although the result is a somewhat clean cave, it is meant only
421 * to give a common structure for the binary cave format. it is not
422 * for archiving purposes (it is better to keep the raw cave as-is)
423 * and it is not meant for serializing (the intermediate structure
424 * is better defined).
426 * acid top is added to acid bottom in both the cave and the eaters.
427 * fake acid (only in v4) does not exist because it adds nothing to
428 * the game, and is different even in different versions of the emc
431 * v4/v5 time is converted to 10x old time (as it should be).
432 * the reason the kingsoft player used 5x time was copy protection.
434 * note: emc v6 converter has an error in converting v4 eaters to the
435 * wrong bug(24 instead of 20) and tank(12 instead of 8).
438 /* changes for game engine integration in Rocks'n'Diamonds:
440 * cave versions below V5 had no grass, but only sand/dirt
441 * - object code 130 (V6 grass) is changed to 189 (V6 dirt)
442 * - object codes are changed in both cave and eater arrays
443 * - only graphical change, as both objects behave the same
446 static const unsigned char map_v6[256] =
450 0,0,2,2, 4,4,118,118, 8,9,10,11, 12,13,14,15,
451 16,16,18,18, 20,21,22,23, 24,25,26,27, 28,28,118,28,
452 0,16,2,18, 36,37,37,37, 40,41,42,43, 44,45,128,128,
453 128,148,148, 148,45,45,45, 148,0,57,58, 59,60,61,62,63,
455 64,65,66,67, 68,69,69,71, 72,73,74,75, 118,75,75,75,
456 75,75,75,75, 75,153,153,153, 153,153,153,153, 153,153,153,153,
457 153,153,153,99, 100,68,68,68, 68,68,68,68, 68,118,118,118,
458 118,118,114,115, 131,118,118,119, 120,121,122,118, 118,118,118,118,
460 128,129,130,131, 132,133,134,135, 136,137,138,139, 140,141,142,143,
461 144,145,146,147, 148,149,150,151, 152,153,154,155, 156,157,158,159,
462 160,161,162,163, 164,165,165,118, 168,169,170,171, 172,173,174,175,
463 176,177,178,179, 180,181,182,183, 184,185,186,187, 188,189,68,191,
465 192,193,194,195, 196,197,198,199, 200,201,202,203, 204,205,206,207,
466 208,209,210,211, 212,213,214,215, 216,217,218,219, 220,221,222,223,
467 224,225,226,227, 228,229,230,231, 232,233,234,235, 236,237,238,239,
468 240,241,242,243, 244,245,153,153, 153,153,153,153, 153,153,153,153
471 static const unsigned char map_v5[256] =
475 0,0,2,2, 4,4,118,118, 8,9,10,11, 12,13,14,15,
476 16,16,18,18, 20,21,22,23, 24,25,26,27, 28,28,118,28,
477 0,16,2,18, 36,37,37,37, 147,41,42,43, 44,45,128,128,
478 128,148,148,148, 45,45,45,148, 0,57,58,59, 60,61,62,63,
480 64,65,66,67, 68,153,153,153, 153,153,153,153, 153,153,153,153,
481 153,153,153,153, 153,153,153,153, 153,153,153,153, 153,153,153,153,
482 153,153,153,153, 153,68,68,68, 68,68,68,68, 68,118,118,118,
483 118,118,114,115, 131,118,118,119, 120,121,122,118, 118,118,118,118,
485 128,129,130,131, 132,133,134,135, 136,137,138,139, 140,141,142,143,
486 144,145,146,147, 148,149,150,151, 152,153,154,155, 156,157,158,159,
487 160,153,153,153, 153,153,153,118, 168,169,170,171, 172,173,174,175,
488 176,177,178,179, 180,181,182,183, 184,185,186,187, 188,189,68,153,
490 153,153,153,153, 153,153,153,153, 200,201,202,203, 204,205,206,207,
491 208,209,210,211, 212,213,214,215, 216,217,218,219, 220,221,222,223,
492 224,225,226,227, 228,229,230,231, 232,233,234,235, 236,237,238,239,
493 240,241,153,153, 153,153,153,153, 153,153,153,153, 153,153,153,153
496 static const unsigned char map_v4[256] =
500 0,0,2,2, 4,4,118,118, 8,9,10,11, 12,13,14,15,
501 16,16,18,18, 20,21,22,23, 24,25,26,27, 28,28,118,28,
502 0,16,2,18, 36,37,37,37, 147,41,42,43, 44,45,128,128,
503 128,148,148,148, 45,45,45,148, 0,153,153,59, 60,61,62,63,
505 64,65,66,153, 153,153,153,153, 153,153,153,153, 153,153,153,153,
506 153,153,153,153, 153,153,153,153, 153,153,153,153, 153,153,153,153,
507 153,153,153,153, 153,153,153,153, 153,153,153,153, 153,153,153,153,
508 153,118,114,115, 131,118,118,119, 120,121,122,118, 118,118,118,118,
510 128,129,189,131, 132,133,134,135, 136,137,138,139, 140,141,142,143,
511 144,145,146,147, 148,149,150,151, 152,68,154,155, 156,157,158,160,
512 160,160,160,160, 160,160,160,160, 160,160,160,160, 160,160,160,175,
513 153,153,153,153, 153,153,153,153, 153,153,153,153, 153,153,68,153,
515 153,153,153,153, 153,153,153,153, 200,201,202,203, 204,205,206,207,
516 208,209,210,211, 212,213,214,215, 216,217,218,219, 220,221,222,223,
517 224,225,226,227, 228,229,230,231, 232,233,234,235, 236,237,238,239,
518 240,241,153,153, 153,153,153,153, 153,153,153,153, 153,153,153,153
521 static const unsigned char map_v4_eater[32] =
523 /* filter for v4 eater */
525 128,18,2,0, 4,8,16,20, 28,37,41,45, 189,129,131,132,
526 133,134,135,136, 146,147,175,65, 66,64,2,18, 128,128,128,128
529 static boolean filename_has_v1_format(char *filename)
531 char *basename = getBaseNamePtr(filename);
533 return (strlen(basename) == 3 &&
534 basename[0] == 'a' &&
535 basename[1] >= 'a' && basename[1] <= 'k' &&
536 basename[2] >= '0' && basename[2] <= '9');
539 int cleanup_em_level(unsigned char *src, int length, char *filename)
541 int file_version = FILE_VERSION_EM_UNKNOWN;
544 if (length >= 2172 &&
545 src[2106] == 255 && /* version id: */
546 src[2107] == 54 && /* '6' */
547 src[2108] == 48 && /* '0' */
548 src[2109] == 48) /* '0' */
550 /* ---------- this cave has V6 file format ---------- */
551 file_version = FILE_VERSION_EM_V6;
553 /* remap elements to internal EMC level format */
554 for (i = 0; i < 2048; i++)
555 src[i] = map_v6[src[i]];
556 for (i = 2048; i < 2084; i++)
557 src[i] = map_v6[src[i]];
558 for (i = 2112; i < 2148; i++)
559 src[i] = map_v6[src[i]];
561 else if (length >= 2110 &&
562 src[2106] == 255 && /* version id: */
563 src[2107] == 53 && /* '5' */
564 src[2108] == 48 && /* '0' */
565 src[2109] == 48) /* '0' */
567 /* ---------- this cave has V5 file format ---------- */
568 file_version = FILE_VERSION_EM_V5;
570 /* remap elements to internal EMC level format */
571 for (i = 0; i < 2048; i++)
572 src[i] = map_v5[src[i]];
573 for (i = 2048; i < 2084; i++)
574 src[i] = map_v5[src[i]];
575 for (i = 2112; i < 2148; i++)
576 src[i] = src[i - 64];
578 else if (length >= 2106 &&
579 (src[1983] == 27 || /* encrypted (only EM I/II/III) */
580 src[1983] == 116 || /* unencrypted (usual case) */
581 src[1983] == 131)) /* unencrypted (rare case) */
583 /* ---------- this cave has V1, V2 or V3 file format ---------- */
585 boolean fix_copyright = FALSE;
588 byte at position 1983 (0x07bf) is used as "magic byte":
589 - 27 (0x1b) => encrypted level (V3 only / Kingsoft original games)
590 - 116 (0x74) => unencrypted level (byte is corrected to 131 (0x83))
591 - 131 (0x83) => unencrypted level (happens only in very rare cases)
594 if (src[1983] == 27) /* (0x1b) -- after decryption: 116 (0x74) */
596 /* this is original (encrypted) Emerald Mine I, II or III level file */
598 int first_byte = src[0];
599 unsigned char code0 = 0x65;
600 unsigned char code1 = 0x11;
602 /* decode encrypted level data */
603 for (i = 0; i < 2106; i++)
608 code0 = (code0 + 7) & 0xff;
611 src[1] = 131; /* needed for all Emerald Mine levels */
613 /* first byte is either 0xf1 (EM I and III) or 0xf5 (EM II) */
614 if (first_byte == 0xf5)
616 src[0] = 131; /* only needed for Emerald Mine II levels */
618 fix_copyright = TRUE;
621 /* ---------- this cave has V3 file format ---------- */
622 file_version = FILE_VERSION_EM_V3;
624 else if (filename_has_v1_format(filename))
626 /* ---------- this cave has V1 file format ---------- */
627 file_version = FILE_VERSION_EM_V1;
631 /* ---------- this cave has V2 file format ---------- */
632 file_version = FILE_VERSION_EM_V2;
635 /* remap elements to internal EMC level format */
636 for (i = 0; i < 2048; i++)
637 src[i] = map_v4[src[i]];
638 for (i = 2048; i < 2084; i++)
639 src[i] = map_v4_eater[src[i] >= 28 ? 0 : src[i]];
640 for (i = 2112; i < 2148; i++)
641 src[i] = src[i - 64];
643 if (fix_copyright) /* fix "(c)" sign in Emerald Mine II levels */
645 for (i = 0; i < 2048; i++)
647 src[i] = 254; /* replace 'Cdecor_1' with 'Calpha_copyr' */
652 /* ---------- this cave has unknown file format ---------- */
654 /* if file has length of old-style level file, print (wrong) magic byte */
656 Error(ERR_WARN, "unknown magic byte 0x%02x at position 0x%04x",
659 return FILE_VERSION_EM_UNKNOWN;
662 if (file_version < FILE_VERSION_EM_V6)
665 src[2106] = 255; /* version id: */
666 src[2107] = 54; /* '6' */
667 src[2108] = 48; /* '0' */
668 src[2109] = 48; /* '0' */
672 /* stored level time of levels for the V2 player was changed to 50% of the
673 time for the V1 player (original V3 levels already considered this) */
674 if (file_version != FILE_VERSION_EM_V1 &&
675 file_version != FILE_VERSION_EM_V3)
680 for (i = 2148; i < 2172; i++)
687 /* ---------- at this stage, the cave data always has V6 format ---------- */
690 for (i = 0; i < 2048; i++)
693 for (i++; i < 2048; i++)
698 for (i = 64; i < 2048; i++)
699 if (src[i] == 63) /* replace element above 'Cacid_s' ... */
700 src[i - 64] = 101; /* ... with 'Cacid_1' */
702 /* fix acid with no base beneath it (see below for details (*)) */
703 for (i = 64; i < 2048 - 1; i++)
705 if (file_version <= FILE_VERSION_EM_V2 &&
706 src[i - 64] == 101 && src[i] != 63) /* acid without base */
708 if (src[i - 1] == 101 || /* remove acid over acid row */
710 src[i - 64] = 6; /* replace element above with 'Cblank' */
712 src[i - 64] = 255; /* replace element above with 'Cfake_acid_1' */
716 /* fix acid in eater 1 */
717 for (i = 2051; i < 2057; i++)
721 /* fix acid in eater 2 */
722 for (i = 2060; i < 2066; i++)
726 /* fix acid in eater 3 */
727 for (i = 2069; i < 2075; i++)
731 /* fix acid in eater 4 */
732 for (i = 2078; i < 2084; i++)
736 /* fix acid in eater 5 */
737 for (i = 2115; i < 2121; i++)
741 /* fix acid in eater 6 */
742 for (i = 2124; i < 2130; i++)
746 /* fix acid in eater 7 */
747 for (i = 2133; i < 2139; i++)
751 /* fix acid in eater 8 */
752 for (i = 2142; i < 2148; i++)
761 src[GET_BE16(src[2096])] = 128;
765 src[GET_BE16(src[2098])] = 128;
775 src[2159] = map_v6[src[2159]];
785 /* size of v6 cave */
789 Error(ERR_DEBUG, "EM level file version: %d", file_version);
798 structure of emerald mine level disk files
799 ----------------------------------------------------------------------
801 if(len >= 2172 && (buf[2106] == 255 && buf[2107] == 54 && buf[2108] == 48 && buf[2109] == 48)) // v6
802 if(len >= 2110 && (buf[2106] == 255 && buf[2107] == 53 && buf[2108] == 48 && buf[2109] == 48)) // v5
803 if(len >= 2106 && (buf[1983] == 116 || buf[2047] == 116)) // v4
804 if(len >= 2106 && (buf[1983] == 27 || buf[2047] == 219)) // v3
806 buf[0]=241;buf[1]=248;for(i=0,j=101;i<2106;i++,j+=7)buf[i]=(buf[i]^j)-17; // decrypt
808 number of movements (calls to logic) = time * 50 / 8
810 {} reserved (but some broken levels use them)
812 ----------------------------------------------------------------------
832 2095: emeralds needed
836 2102: wonderwall time
838 2106: ID (0xff363030)
844 2148: flags bit#7=NOI #6=RIS
845 2149: wind direction bit#0=right #1=down #2=left #3=up
846 2150: cave number bit#7=teamwork
855 2162: ball info bit#15=switch state #8=random
856 ; bit#0=N #1=S #2=W #3=E #4=SE #5=SW #6=NE #7=NW
857 2164: android move speed
858 2166: android clone speed
860 ; bit#0=emerald #1=diamond #2=stone #3=bomb #4=nut #5=tank #6=eater
861 ; #7=bug #8=alien #9=spring #10=balloon #11=ameuba #12=dynamite
866 1: stone {stone_fall}
868 3: diamond {diamond_fall}
870 5: alien {alien_pause}
884 19: emerald {emerald_fall}
895 30: blank {drip_stretchB}
896 31: drip {drip_stretch}
897 32: stone {stone_pause}
898 33: bomb {bomb_pause}
899 34: diamond {diamond_pause}
900 35: emerald {emerald_pause}
901 36: wonderwall {wonderwallB}
911 46: blank {sand_stonein_2}
912 47: blank {sand_stonein_3}
913 48: blank {sand_stonein_4}
914 49: sand {sand_stonesand_2}
915 50: sand {sand_stonesand_3}
916 51: sand {sand_stonesand_4}
917 52: sand_stone {sand_sandstone_2}
918 53: sand_stone {sand_sandstone_3}
919 54: sand_stone {sand_sandstone_4}
920 55: sand {sand_stonesand_4}
921 56: stone {sand_stoneout_2}
935 70: spring {spring_fall}
936 71: spring {spring_w}
937 72: spring {spring_e}
942 77: android {android_n_1}
943 78: android {android_n_2}
944 79: android {android_s_1}
945 80: android {android_s_2}
946 81: android {android_e_1}
947 82: android {android_e_2}
948 83: android {android_w_1}
949 84: android {android_w_2}
964 99: spring {push_spring_w}
965 100: spring {push_spring_e}
974 109: pause {grass_wB}
975 110: pause {grass_eB}
976 111: pause {grass_nB}
977 112: pause {grass_sB}
978 113: pause {dynamite_blank}
979 114: nut {push_nut_w}
980 115: nut {push_nut_e}
981 116: steel_2 {end of level}
983 118: pause {emerald_blank}
984 119: bomb {push_bomb_w}
985 120: bomb {push_bomb_e}
986 121: stone {push_stone_w}
987 122: stone {push_stone_e}
988 123: pause {diamond_blank}
1029 163: fake_blank {fake_blankB}
1030 164: fake_grass {fake_grassB}
1032 166: switch {switchB}
1123 ----------------------------------------------------------------------
1139 2091: dynamite value
1143 2095: emeralds needed
1147 2102: wonderwall time
1149 2106: ID (0xff353030)
1153 1: stone {stone_fall}
1155 3: diamond {diamond_fall}
1157 5: alien {alien_pause}
1169 17: bomb {bomb_fall}
1171 19: emerald {emerald_fall}
1181 29: drip {drip_fall}
1182 30: blank {drip_stretchB}
1183 31: drip {drip_stretch}
1184 32: stone {stone_pause}
1185 33: bomb {bomb_pause}
1186 34: diamond {diamond_pause}
1187 35: emerald {emerald_pause}
1188 36: wonderwall {wonderwallB}
1198 46: blank {sand_stonein_2}
1199 47: blank {sand_stonein_3}
1200 48: blank {sand_stonein_4}
1201 49: sand {sand_stonesand_2}
1202 50: sand {sand_stonesand_3}
1203 51: sand {sand_stonesand_4}
1204 52: sand_stone {sand_sandstone_2}
1205 53: sand_stone {sand_sandstone_3}
1206 54: sand_stone {sand_sandstone_4}
1207 55: sand {sand_stonesand_4}
1208 56: stone {sand_stoneout_2}
1261 109: pause {grass_wB}
1262 110: pause {grass_eB}
1263 111: pause {grass_nB}
1264 112: pause {grass_sB}
1265 113: pause {dynamite_blank}
1266 114: nut {push_nut_w}
1267 115: nut {push_nut_e}
1268 116: steel_2 {end of level}
1269 117: dynamite_4 {boom_2}
1270 118: pause {emerald_blank}
1271 119: bomb {push_bomb_w}
1272 120: bomb {push_bomb_e}
1273 121: stone {push_stone_w}
1274 122: stone {push_stone_e}
1275 123: pause {diamond_blank}
1276 124: pause {dirt_wB}
1277 125: pause {dirt_eB}
1278 126: pause {dirt_nB}
1279 127: pause {dirt_sB}
1410 ----------------------------------------------------------------------
1426 2091: dynamite value
1430 2095: emeralds needed
1434 2102: wonderwall time
1464 26: diamond {diamond_shine}
1465 27: emerald {emerald_shine}
1468 1: stone {stone_fall}
1470 3: diamond {diamond_fall}
1472 5: alien {alien_pause}
1484 17: bomb {bomb_fall}
1486 19: emerald {emerald_fall}
1496 29: drip {drip_fall}
1497 30: blank {drip_stretchB}
1498 31: drip {drip_stretch}
1499 32: stone {stone_pause}
1500 33: bomb {bomb_pause}
1501 34: diamond {diamond_pause}
1502 35: emerald {emerald_pause}
1503 36: wonderwall {wonderwallB}
1513 46: blank {sand_stonein_2}
1514 47: blank {sand_stonein_3}
1515 48: blank {sand_stonein_4}
1516 49: sand {sand_stonesand_2}
1517 50: sand {sand_stonesand_3}
1518 51: sand {sand_stonesand_4}
1519 52: sand_stone {sand_sandstone_2}
1520 53: sand_stone {sand_sandstone_3}
1521 54: sand_stone {sand_sandstone_4}
1522 55: sand {sand_stonesand_4}
1523 56: stone {sand_stoneout_2}
1580 113: pause {dynamite_blank}
1581 114: nut {push_nut_w}
1582 115: nut {push_nut_e}
1583 116: steel_1 {end of level}
1584 117: dynamite_4 {boom_2}
1585 118: pause {emerald_blank}
1586 119: bomb {push_bomb_w}
1587 120: bomb {push_bomb_e}
1588 121: stone {push_stone_w}
1589 122: stone {push_stone_e}
1590 123: pause {diamond_blank}
1591 124: pause {dirt_wB}
1592 125: pause {dirt_eB}
1593 126: pause {dirt_nB}
1594 127: pause {dirt_sB}
1627 159: fake_grass {dirt}
1628 160: fake_grass {dirt}
1629 161: fake_grass {dirt}
1630 162: fake_grass {dirt}
1631 163: fake_grass {dirt}
1632 164: fake_grass {dirt}
1633 165: fake_grass {dirt}
1634 166: fake_grass {dirt}
1635 167: fake_grass {dirt}
1636 168: fake_grass {dirt}
1637 169: fake_grass {dirt}
1638 170: fake_grass {dirt}
1639 171: fake_grass {dirt}
1640 172: fake_grass {dirt}
1641 173: fake_grass {dirt}
1642 174: fake_grass {dirt}
1708 240: alpha_arrow_e {}
1709 241: decor_1 {alpha_copyr}
1725 ----------------------------------------------------------------------