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 */
276 cav.time_seconds = MIN(GET_BE16(src[2110]), 9999);
277 cav.gems_needed = src[2095];
280 cav.testmode = FALSE;
281 cav.teamwork = (src[2150] & 128) != 0;
285 cav.emerald_score = src[2084];
286 cav.diamond_score = src[2085];
287 cav.alien_score = src[2086];
288 cav.tank_score = src[2087];
289 cav.bug_score = src[2088];
290 cav.eater_score = src[2089];
291 cav.nut_score = src[2090];
292 cav.dynamite_score = src[2091];
293 cav.key_score = src[2092];
294 cav.exit_score = src[2093] * 8 / 5;
296 cav.lenses_score = src[2151];
297 cav.magnify_score = src[2152];
298 cav.slurp_score = src[2153];
302 cav.android_move_time = MIN(GET_BE16(src[2164]), 9999);
303 cav.android_clone_time = MIN(GET_BE16(src[2166]), 9999);
304 cav.ball_time = MIN(GET_BE16(src[2160]), 9999);
306 cav.lenses_time = MIN(GET_BE16(src[2154]), 9999);
307 cav.magnify_time = MIN(GET_BE16(src[2156]), 9999);
308 cav.wheel_time = MIN(GET_BE16(src[2104]), 9999);
310 cav.amoeba_time = MIN(GET_BE16(src[2100]) * 28, 9999);
311 cav.wonderwall_time = MIN(GET_BE16(src[2102]), 9999);
313 cav.wind_time = 9999;
315 cav.wind_direction = (temp & 8 ? 0 :
322 cav.ball_random = (src[2162] & 1) != 0;
323 cav.ball_active = (src[2162] & 128) != 0;
325 cav.wonderwall_active = FALSE;
326 cav.wheel_active = FALSE;
327 cav.lenses_active = FALSE;
328 cav.magnify_active = FALSE;
330 for (temp = 1; temp < 2047; temp++)
334 case 36: /* wonderwall */
335 cav.wonderwall_active = TRUE;
336 cav.wonderwall_time = 9999;
340 cav.wheel_active = TRUE;
341 cav.wheel_x = temp % 64;
342 cav.wheel_y = temp / 64;
345 case 163: /* fake blank */
346 cav.lenses_active = TRUE;
349 case 164: /* fake grass */
350 cav.magnify_active = TRUE;
357 temp = GET_BE16(src[2168]);
359 for (i = 0; i < GAME_TILE_MAX; i++)
360 cav.android_array[i] = Cblank;
362 for (i = 0; android_clone_table[i].bit_nr != -1; i++)
363 if (temp & (1 << android_clone_table[i].bit_nr))
364 cav.android_array[android_clone_table[i].clone_from] =
365 android_clone_table[i].clone_to;
369 for (i = 0; i < 8; i++)
370 for (x = 0; x < 9; x++)
371 cav.eater_array[i][x] = map_emc[src[eater_offset[i] + x]];
375 temp = map_emc[src[2159]];
377 for (y = 0; y < 8; y++)
381 for (x = 0; x < 8; x++)
382 cav.ball_array[y][x] = temp;
386 cav.ball_array[y][1] = (src[2163] & 1) ? temp : Cblank; /* north */
387 cav.ball_array[y][6] = (src[2163] & 2) ? temp : Cblank; /* south */
388 cav.ball_array[y][3] = (src[2163] & 4) ? temp : Cblank; /* west */
389 cav.ball_array[y][4] = (src[2163] & 8) ? temp : Cblank; /* east */
390 cav.ball_array[y][7] = (src[2163] & 16) ? temp : Cblank; /* southeast */
391 cav.ball_array[y][5] = (src[2163] & 32) ? temp : Cblank; /* southwest */
392 cav.ball_array[y][2] = (src[2163] & 64) ? temp : Cblank; /* northeast */
393 cav.ball_array[y][0] = (src[2163] & 128)? temp : Cblank; /* northwest */
399 for (i = 0; i < 2; i++)
401 temp = GET_BE16(src[2096 + i * 2]);
403 cav.player_x[i] = (temp & 63);
404 cav.player_y[i] = (temp >> 6 & 31);
409 /* first fill the complete playfield with the empty space element */
410 for (y = 0; y < CAVE_HEIGHT; y++)
411 for (x = 0; x < CAVE_WIDTH; x++)
412 cav.cave[x][y] = Cblank;
414 /* then copy the real level contents from level file into the playfield */
416 for (y = 0; y < cav.height; y++)
417 for (x = 0; x < cav.width; x++)
418 cav.cave[x][y] = map_emc[src[temp++]];
420 native_em_level.file_version = file_version;
424 /* convert all emerald mine caves to emc version 6 cave format.
426 * caves are filtered to get rid of invalid or unsupported tiles.
428 * although the result is a somewhat clean cave, it is meant only
429 * to give a common structure for the binary cave format. it is not
430 * for archiving purposes (it is better to keep the raw cave as-is)
431 * and it is not meant for serializing (the intermediate structure
432 * is better defined).
434 * acid top is added to acid bottom in both the cave and the eaters.
435 * fake acid (only in v4) does not exist because it adds nothing to
436 * the game, and is different even in different versions of the emc
439 * v4/v5 time is converted to 10x old time (as it should be).
440 * the reason the kingsoft player used 5x time was copy protection.
442 * note: emc v6 converter has an error in converting v4 eaters to the
443 * wrong bug(24 instead of 20) and tank(12 instead of 8).
446 /* changes for game engine integration in Rocks'n'Diamonds:
448 * cave versions below V5 had no grass, but only sand/dirt
449 * - object code 130 (V6 grass) is changed to 189 (V6 dirt)
450 * - object codes are changed in both cave and eater arrays
451 * - only graphical change, as both objects behave the same
454 static const unsigned char map_v6[256] =
458 0,0,2,2, 4,4,118,118, 8,9,10,11, 12,13,14,15,
459 16,16,18,18, 20,21,22,23, 24,25,26,27, 28,28,118,28,
460 0,16,2,18, 36,37,37,37, 40,41,42,43, 44,45,128,128,
461 128,148,148, 148,45,45,45, 148,0,57,58, 59,60,61,62,63,
463 64,65,66,67, 68,69,69,71, 72,73,74,75, 118,75,75,75,
464 75,75,75,75, 75,153,153,153, 153,153,153,153, 153,153,153,153,
465 153,153,153,99, 100,68,68,68, 68,68,68,68, 68,118,118,118,
466 118,118,114,115, 131,118,118,119, 120,121,122,118, 118,118,118,118,
468 128,129,130,131, 132,133,134,135, 136,137,138,139, 140,141,142,143,
469 144,145,146,147, 148,149,150,151, 152,153,154,155, 156,157,158,159,
470 160,161,162,163, 164,165,165,118, 168,169,170,171, 172,173,174,175,
471 176,177,178,179, 180,181,182,183, 184,185,186,187, 188,189,68,191,
473 192,193,194,195, 196,197,198,199, 200,201,202,203, 204,205,206,207,
474 208,209,210,211, 212,213,214,215, 216,217,218,219, 220,221,222,223,
475 224,225,226,227, 228,229,230,231, 232,233,234,235, 236,237,238,239,
476 240,241,242,243, 244,245,153,153, 153,153,153,153, 153,153,153,153
479 static const unsigned char map_v5[256] =
483 0,0,2,2, 4,4,118,118, 8,9,10,11, 12,13,14,15,
484 16,16,18,18, 20,21,22,23, 24,25,26,27, 28,28,118,28,
485 0,16,2,18, 36,37,37,37, 147,41,42,43, 44,45,128,128,
486 128,148,148,148, 45,45,45,148, 0,57,58,59, 60,61,62,63,
488 64,65,66,67, 68,153,153,153, 153,153,153,153, 153,153,153,153,
489 153,153,153,153, 153,153,153,153, 153,153,153,153, 153,153,153,153,
490 153,153,153,153, 153,68,68,68, 68,68,68,68, 68,118,118,118,
491 118,118,114,115, 131,118,118,119, 120,121,122,118, 118,118,118,118,
493 128,129,130,131, 132,133,134,135, 136,137,138,139, 140,141,142,143,
494 144,145,146,147, 148,149,150,151, 152,153,154,155, 156,157,158,159,
495 160,153,153,153, 153,153,153,118, 168,169,170,171, 172,173,174,175,
496 176,177,178,179, 180,181,182,183, 184,185,186,187, 188,189,68,153,
498 153,153,153,153, 153,153,153,153, 200,201,202,203, 204,205,206,207,
499 208,209,210,211, 212,213,214,215, 216,217,218,219, 220,221,222,223,
500 224,225,226,227, 228,229,230,231, 232,233,234,235, 236,237,238,239,
501 240,241,153,153, 153,153,153,153, 153,153,153,153, 153,153,153,153
504 static const unsigned char map_v4[256] =
508 0,0,2,2, 4,4,118,118, 8,9,10,11, 12,13,14,15,
509 16,16,18,18, 20,21,22,23, 24,25,26,27, 28,28,118,28,
510 0,16,2,18, 36,37,37,37, 147,41,42,43, 44,45,128,128,
511 128,148,148,148, 45,45,45,148, 0,153,153,59, 60,61,62,63,
513 64,65,66,153, 153,153,153,153, 153,153,153,153, 153,153,153,153,
514 153,153,153,153, 153,153,153,153, 153,153,153,153, 153,153,153,153,
515 153,153,153,153, 153,153,153,153, 153,153,153,153, 153,153,153,153,
516 153,118,114,115, 131,118,118,119, 120,121,122,118, 118,118,118,118,
518 128,129,189,131, 132,133,134,135, 136,137,138,139, 140,141,142,143,
519 144,145,146,147, 148,149,150,151, 152,68,154,155, 156,157,158,160,
520 160,160,160,160, 160,160,160,160, 160,160,160,160, 160,160,160,175,
521 153,153,153,153, 153,153,153,153, 153,153,153,153, 153,153,68,153,
523 153,153,153,153, 153,153,153,153, 200,201,202,203, 204,205,206,207,
524 208,209,210,211, 212,213,214,215, 216,217,218,219, 220,221,222,223,
525 224,225,226,227, 228,229,230,231, 232,233,234,235, 236,237,238,239,
526 240,241,153,153, 153,153,153,153, 153,153,153,153, 153,153,153,153
529 static const unsigned char map_v4_eater[32] =
531 /* filter for v4 eater */
533 128,18,2,0, 4,8,16,20, 28,37,41,45, 189,129,131,132,
534 133,134,135,136, 146,147,175,65, 66,64,2,18, 128,128,128,128
537 static boolean filename_has_v1_format(char *filename)
539 char *basename = getBaseNamePtr(filename);
541 return (strlen(basename) == 3 &&
542 basename[0] == 'a' &&
543 basename[1] >= 'a' && basename[1] <= 'k' &&
544 basename[2] >= '0' && basename[2] <= '9');
547 int cleanup_em_level(unsigned char *src, int length, char *filename)
549 int file_version = FILE_VERSION_EM_UNKNOWN;
552 if (length >= 2172 &&
553 src[2106] == 255 && /* version id: */
554 src[2107] == 54 && /* '6' */
555 src[2108] == 48 && /* '0' */
556 src[2109] == 48) /* '0' */
558 /* ---------- this cave has V6 file format ---------- */
559 file_version = FILE_VERSION_EM_V6;
561 /* remap elements to internal EMC level format */
562 for (i = 0; i < 2048; i++)
563 src[i] = map_v6[src[i]];
564 for (i = 2048; i < 2084; i++)
565 src[i] = map_v6[src[i]];
566 for (i = 2112; i < 2148; i++)
567 src[i] = map_v6[src[i]];
569 else if (length >= 2110 &&
570 src[2106] == 255 && /* version id: */
571 src[2107] == 53 && /* '5' */
572 src[2108] == 48 && /* '0' */
573 src[2109] == 48) /* '0' */
575 /* ---------- this cave has V5 file format ---------- */
576 file_version = FILE_VERSION_EM_V5;
578 /* remap elements to internal EMC level format */
579 for (i = 0; i < 2048; i++)
580 src[i] = map_v5[src[i]];
581 for (i = 2048; i < 2084; i++)
582 src[i] = map_v5[src[i]];
583 for (i = 2112; i < 2148; i++)
584 src[i] = src[i - 64];
586 else if (length >= 2106 &&
587 (src[1983] == 27 || /* encrypted (only EM I/II/III) */
588 src[1983] == 116 || /* unencrypted (usual case) */
589 src[1983] == 131)) /* unencrypted (rare case) */
591 /* ---------- this cave has V1, V2 or V3 file format ---------- */
593 boolean fix_copyright = FALSE;
596 byte at position 1983 (0x07bf) is used as "magic byte":
597 - 27 (0x1b) => encrypted level (V3 only / Kingsoft original games)
598 - 116 (0x74) => unencrypted level (byte is corrected to 131 (0x83))
599 - 131 (0x83) => unencrypted level (happens only in very rare cases)
602 if (src[1983] == 27) /* (0x1b) -- after decryption: 116 (0x74) */
604 /* this is original (encrypted) Emerald Mine I, II or III level file */
606 int first_byte = src[0];
607 unsigned char code0 = 0x65;
608 unsigned char code1 = 0x11;
610 /* decode encrypted level data */
611 for (i = 0; i < 2106; i++)
616 code0 = (code0 + 7) & 0xff;
619 src[1] = 131; /* needed for all Emerald Mine levels */
621 /* first byte is either 0xf1 (EM I and III) or 0xf5 (EM II) */
622 if (first_byte == 0xf5)
624 src[0] = 131; /* only needed for Emerald Mine II levels */
626 fix_copyright = TRUE;
629 /* ---------- this cave has V3 file format ---------- */
630 file_version = FILE_VERSION_EM_V3;
632 else if (filename_has_v1_format(filename))
634 /* ---------- this cave has V1 file format ---------- */
635 file_version = FILE_VERSION_EM_V1;
639 /* ---------- this cave has V2 file format ---------- */
640 file_version = FILE_VERSION_EM_V2;
643 /* remap elements to internal EMC level format */
644 for (i = 0; i < 2048; i++)
645 src[i] = map_v4[src[i]];
646 for (i = 2048; i < 2084; i++)
647 src[i] = map_v4_eater[src[i] >= 28 ? 0 : src[i]];
648 for (i = 2112; i < 2148; i++)
649 src[i] = src[i - 64];
651 if (fix_copyright) /* fix "(c)" sign in Emerald Mine II levels */
653 for (i = 0; i < 2048; i++)
655 src[i] = 254; /* replace 'Cdecor_1' with 'Calpha_copyr' */
660 /* ---------- this cave has unknown file format ---------- */
662 /* if file has length of old-style level file, print (wrong) magic byte */
664 Error(ERR_WARN, "unknown magic byte 0x%02x at position 0x%04x",
667 return FILE_VERSION_EM_UNKNOWN;
670 if (file_version < FILE_VERSION_EM_V6)
673 src[2106] = 255; /* version id: */
674 src[2107] = 54; /* '6' */
675 src[2108] = 48; /* '0' */
676 src[2109] = 48; /* '0' */
680 /* stored level time of levels for the V2 player was changed to 50% of the
681 time for the V1 player (original V3 levels already considered this) */
682 if (file_version != FILE_VERSION_EM_V1 &&
683 file_version != FILE_VERSION_EM_V3)
688 for (i = 2148; i < 2172; i++)
695 /* ---------- at this stage, the cave data always has V6 format ---------- */
698 for (i = 0; i < 2048; i++)
701 for (i++; i < 2048; i++)
706 for (i = 64; i < 2048; i++)
707 if (src[i] == 63) /* replace element above 'Cacid_s' ... */
708 src[i - 64] = 101; /* ... with 'Cacid_1' */
710 /* fix acid with no base beneath it (see below for details (*)) */
711 for (i = 64; i < 2048 - 1; i++)
713 if (file_version <= FILE_VERSION_EM_V2 &&
714 src[i - 64] == 101 && src[i] != 63) /* acid without base */
716 if (src[i - 1] == 101 || /* remove acid over acid row */
718 src[i - 64] = 6; /* replace element above with 'Cblank' */
720 src[i - 64] = 255; /* replace element above with 'Cfake_acid_1' */
724 /* fix acid in eater 1 */
725 for (i = 2051; i < 2057; i++)
729 /* fix acid in eater 2 */
730 for (i = 2060; i < 2066; i++)
734 /* fix acid in eater 3 */
735 for (i = 2069; i < 2075; i++)
739 /* fix acid in eater 4 */
740 for (i = 2078; i < 2084; i++)
744 /* fix acid in eater 5 */
745 for (i = 2115; i < 2121; i++)
749 /* fix acid in eater 6 */
750 for (i = 2124; i < 2130; i++)
754 /* fix acid in eater 7 */
755 for (i = 2133; i < 2139; i++)
759 /* fix acid in eater 8 */
760 for (i = 2142; i < 2148; i++)
769 src[GET_BE16(src[2096])] = 128;
773 src[GET_BE16(src[2098])] = 128;
783 src[2159] = map_v6[src[2159]];
793 /* size of v6 cave */
797 Error(ERR_DEBUG, "EM level file version: %d", file_version);
806 structure of emerald mine level disk files
807 ----------------------------------------------------------------------
809 if(len >= 2172 && (buf[2106] == 255 && buf[2107] == 54 && buf[2108] == 48 && buf[2109] == 48)) // v6
810 if(len >= 2110 && (buf[2106] == 255 && buf[2107] == 53 && buf[2108] == 48 && buf[2109] == 48)) // v5
811 if(len >= 2106 && (buf[1983] == 116 || buf[2047] == 116)) // v4
812 if(len >= 2106 && (buf[1983] == 27 || buf[2047] == 219)) // v3
814 buf[0]=241;buf[1]=248;for(i=0,j=101;i<2106;i++,j+=7)buf[i]=(buf[i]^j)-17; // decrypt
816 number of movements (calls to logic) = time * 50 / 8
818 {} reserved (but some broken levels use them)
820 ----------------------------------------------------------------------
840 2095: emeralds needed
844 2102: wonderwall time
846 2106: ID (0xff363030)
852 2148: flags bit#7=NOI #6=RIS
853 2149: wind direction bit#0=right #1=down #2=left #3=up
854 2150: cave number bit#7=teamwork
863 2162: ball info bit#15=switch state #8=random
864 ; bit#0=N #1=S #2=W #3=E #4=SE #5=SW #6=NE #7=NW
865 2164: android move speed
866 2166: android clone speed
868 ; bit#0=emerald #1=diamond #2=stone #3=bomb #4=nut #5=tank #6=eater
869 ; #7=bug #8=alien #9=spring #10=balloon #11=ameuba #12=dynamite
874 1: stone {stone_fall}
876 3: diamond {diamond_fall}
878 5: alien {alien_pause}
892 19: emerald {emerald_fall}
903 30: blank {drip_stretchB}
904 31: drip {drip_stretch}
905 32: stone {stone_pause}
906 33: bomb {bomb_pause}
907 34: diamond {diamond_pause}
908 35: emerald {emerald_pause}
909 36: wonderwall {wonderwallB}
919 46: blank {sand_stonein_2}
920 47: blank {sand_stonein_3}
921 48: blank {sand_stonein_4}
922 49: sand {sand_stonesand_2}
923 50: sand {sand_stonesand_3}
924 51: sand {sand_stonesand_4}
925 52: sand_stone {sand_sandstone_2}
926 53: sand_stone {sand_sandstone_3}
927 54: sand_stone {sand_sandstone_4}
928 55: sand {sand_stonesand_4}
929 56: stone {sand_stoneout_2}
943 70: spring {spring_fall}
944 71: spring {spring_w}
945 72: spring {spring_e}
950 77: android {android_n_1}
951 78: android {android_n_2}
952 79: android {android_s_1}
953 80: android {android_s_2}
954 81: android {android_e_1}
955 82: android {android_e_2}
956 83: android {android_w_1}
957 84: android {android_w_2}
972 99: spring {push_spring_w}
973 100: spring {push_spring_e}
982 109: pause {grass_wB}
983 110: pause {grass_eB}
984 111: pause {grass_nB}
985 112: pause {grass_sB}
986 113: pause {dynamite_blank}
987 114: nut {push_nut_w}
988 115: nut {push_nut_e}
989 116: steel_2 {end of level}
991 118: pause {emerald_blank}
992 119: bomb {push_bomb_w}
993 120: bomb {push_bomb_e}
994 121: stone {push_stone_w}
995 122: stone {push_stone_e}
996 123: pause {diamond_blank}
1000 127: pause {dirt_sB}
1037 163: fake_blank {fake_blankB}
1038 164: fake_grass {fake_grassB}
1040 166: switch {switchB}
1131 ----------------------------------------------------------------------
1147 2091: dynamite value
1151 2095: emeralds needed
1155 2102: wonderwall time
1157 2106: ID (0xff353030)
1161 1: stone {stone_fall}
1163 3: diamond {diamond_fall}
1165 5: alien {alien_pause}
1177 17: bomb {bomb_fall}
1179 19: emerald {emerald_fall}
1189 29: drip {drip_fall}
1190 30: blank {drip_stretchB}
1191 31: drip {drip_stretch}
1192 32: stone {stone_pause}
1193 33: bomb {bomb_pause}
1194 34: diamond {diamond_pause}
1195 35: emerald {emerald_pause}
1196 36: wonderwall {wonderwallB}
1206 46: blank {sand_stonein_2}
1207 47: blank {sand_stonein_3}
1208 48: blank {sand_stonein_4}
1209 49: sand {sand_stonesand_2}
1210 50: sand {sand_stonesand_3}
1211 51: sand {sand_stonesand_4}
1212 52: sand_stone {sand_sandstone_2}
1213 53: sand_stone {sand_sandstone_3}
1214 54: sand_stone {sand_sandstone_4}
1215 55: sand {sand_stonesand_4}
1216 56: stone {sand_stoneout_2}
1269 109: pause {grass_wB}
1270 110: pause {grass_eB}
1271 111: pause {grass_nB}
1272 112: pause {grass_sB}
1273 113: pause {dynamite_blank}
1274 114: nut {push_nut_w}
1275 115: nut {push_nut_e}
1276 116: steel_2 {end of level}
1277 117: dynamite_4 {boom_2}
1278 118: pause {emerald_blank}
1279 119: bomb {push_bomb_w}
1280 120: bomb {push_bomb_e}
1281 121: stone {push_stone_w}
1282 122: stone {push_stone_e}
1283 123: pause {diamond_blank}
1284 124: pause {dirt_wB}
1285 125: pause {dirt_eB}
1286 126: pause {dirt_nB}
1287 127: pause {dirt_sB}
1418 ----------------------------------------------------------------------
1434 2091: dynamite value
1438 2095: emeralds needed
1442 2102: wonderwall time
1472 26: diamond {diamond_shine}
1473 27: emerald {emerald_shine}
1476 1: stone {stone_fall}
1478 3: diamond {diamond_fall}
1480 5: alien {alien_pause}
1492 17: bomb {bomb_fall}
1494 19: emerald {emerald_fall}
1504 29: drip {drip_fall}
1505 30: blank {drip_stretchB}
1506 31: drip {drip_stretch}
1507 32: stone {stone_pause}
1508 33: bomb {bomb_pause}
1509 34: diamond {diamond_pause}
1510 35: emerald {emerald_pause}
1511 36: wonderwall {wonderwallB}
1521 46: blank {sand_stonein_2}
1522 47: blank {sand_stonein_3}
1523 48: blank {sand_stonein_4}
1524 49: sand {sand_stonesand_2}
1525 50: sand {sand_stonesand_3}
1526 51: sand {sand_stonesand_4}
1527 52: sand_stone {sand_sandstone_2}
1528 53: sand_stone {sand_sandstone_3}
1529 54: sand_stone {sand_sandstone_4}
1530 55: sand {sand_stonesand_4}
1531 56: stone {sand_stoneout_2}
1588 113: pause {dynamite_blank}
1589 114: nut {push_nut_w}
1590 115: nut {push_nut_e}
1591 116: steel_1 {end of level}
1592 117: dynamite_4 {boom_2}
1593 118: pause {emerald_blank}
1594 119: bomb {push_bomb_w}
1595 120: bomb {push_bomb_e}
1596 121: stone {push_stone_w}
1597 122: stone {push_stone_e}
1598 123: pause {diamond_blank}
1599 124: pause {dirt_wB}
1600 125: pause {dirt_eB}
1601 126: pause {dirt_nB}
1602 127: pause {dirt_sB}
1635 159: fake_grass {dirt}
1636 160: fake_grass {dirt}
1637 161: fake_grass {dirt}
1638 162: fake_grass {dirt}
1639 163: fake_grass {dirt}
1640 164: fake_grass {dirt}
1641 165: fake_grass {dirt}
1642 166: fake_grass {dirt}
1643 167: fake_grass {dirt}
1644 168: fake_grass {dirt}
1645 169: fake_grass {dirt}
1646 170: fake_grass {dirt}
1647 171: fake_grass {dirt}
1648 172: fake_grass {dirt}
1649 173: fake_grass {dirt}
1650 174: fake_grass {dirt}
1716 240: alpha_arrow_e {}
1717 241: decor_1 {alpha_copyr}
1733 ----------------------------------------------------------------------