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 static int eater_offset[8] =
264 2048, 2057, 2066, 2075,
265 2112, 2121, 2130, 2139
268 void convert_em_level(unsigned char *src, int file_version)
272 /* common to all emc caves */
277 cav.time_seconds = MIN(GET_BE16(src[2110]), 9999);
278 cav.gems_needed = src[2095];
281 cav.testmode = FALSE;
282 cav.teamwork = (src[2150] & 128) != 0;
286 cav.emerald_score = src[2084];
287 cav.diamond_score = src[2085];
288 cav.alien_score = src[2086];
289 cav.tank_score = src[2087];
290 cav.bug_score = src[2088];
291 cav.eater_score = src[2089];
292 cav.nut_score = src[2090];
293 cav.dynamite_score = src[2091];
294 cav.key_score = src[2092];
295 cav.exit_score = src[2093] * 8 / 5;
297 cav.lenses_score = src[2151];
298 cav.magnify_score = src[2152];
299 cav.slurp_score = src[2153];
303 cav.android_move_time = MIN(GET_BE16(src[2164]), 9999);
304 cav.android_clone_time = MIN(GET_BE16(src[2166]), 9999);
305 cav.ball_time = MIN(GET_BE16(src[2160]), 9999);
307 cav.lenses_time = MIN(GET_BE16(src[2154]), 9999);
308 cav.magnify_time = MIN(GET_BE16(src[2156]), 9999);
309 cav.wheel_time = MIN(GET_BE16(src[2104]), 9999);
311 cav.amoeba_time = MIN(GET_BE16(src[2100]) * 28, 9999);
312 cav.wonderwall_time = MIN(GET_BE16(src[2102]), 9999);
314 cav.wind_time = 9999;
316 cav.wind_direction = (temp & 8 ? 0 :
323 cav.ball_random = (src[2162] & 1) != 0;
324 cav.ball_active = (src[2162] & 128) != 0;
326 cav.wonderwall_active = FALSE;
327 cav.wheel_active = FALSE;
328 cav.lenses_active = FALSE;
329 cav.magnify_active = FALSE;
331 for (temp = 1; temp < 2047; temp++)
335 case 36: /* wonderwall */
336 cav.wonderwall_active = TRUE;
337 cav.wonderwall_time = 9999;
341 cav.wheel_active = TRUE;
342 cav.wheel_x = temp % 64;
343 cav.wheel_y = temp / 64;
346 case 163: /* fake blank */
347 cav.lenses_active = TRUE;
350 case 164: /* fake grass */
351 cav.magnify_active = TRUE;
358 temp = GET_BE16(src[2168]);
360 for (i = 0; i < GAME_TILE_MAX; i++)
361 cav.android_array[i] = Cblank;
363 for (i = 0; android_clone_table[i].bit_nr != -1; i++)
364 if (temp & (1 << android_clone_table[i].bit_nr))
365 cav.android_array[android_clone_table[i].clone_from] =
366 android_clone_table[i].clone_to;
370 for (i = 0; i < 8; i++)
371 for (x = 0; x < 9; x++)
372 cav.eater_array[i][x] = map_emc[src[eater_offset[i] + x]];
376 temp = map_emc[src[2159]];
378 for (y = 0; y < 8; y++)
382 for (x = 0; x < 8; x++)
383 cav.ball_array[y][x] = temp;
387 cav.ball_array[y][1] = (src[2163] & 1) ? temp : Cblank; /* north */
388 cav.ball_array[y][6] = (src[2163] & 2) ? temp : Cblank; /* south */
389 cav.ball_array[y][3] = (src[2163] & 4) ? temp : Cblank; /* west */
390 cav.ball_array[y][4] = (src[2163] & 8) ? temp : Cblank; /* east */
391 cav.ball_array[y][7] = (src[2163] & 16) ? temp : Cblank; /* southeast */
392 cav.ball_array[y][5] = (src[2163] & 32) ? temp : Cblank; /* southwest */
393 cav.ball_array[y][2] = (src[2163] & 64) ? temp : Cblank; /* northeast */
394 cav.ball_array[y][0] = (src[2163] & 128)? temp : Cblank; /* northwest */
400 for (i = 0; i < 2; i++)
402 temp = GET_BE16(src[2096 + i * 2]);
404 cav.player_x[i] = (temp & 63);
405 cav.player_y[i] = (temp >> 6 & 31);
410 /* first fill the complete playfield with the empty space element */
411 for (y = 0; y < CAVE_HEIGHT; y++)
412 for (x = 0; x < CAVE_WIDTH; x++)
413 cav.cave[x][y] = Cblank;
415 /* then copy the real level contents from level file into the playfield */
417 for (y = 0; y < cav.height; y++)
418 for (x = 0; x < cav.width; x++)
419 cav.cave[x][y] = map_emc[src[temp++]];
421 native_em_level.file_version = file_version;
425 /* convert all emerald mine caves to emc version 6 cave format.
427 * caves are filtered to get rid of invalid or unsupported tiles.
429 * although the result is a somewhat clean cave, it is meant only
430 * to give a common structure for the binary cave format. it is not
431 * for archiving purposes (it is better to keep the raw cave as-is)
432 * and it is not meant for serializing (the intermediate structure
433 * is better defined).
435 * acid top is added to acid bottom in both the cave and the eaters.
436 * fake acid (only in v4) does not exist because it adds nothing to
437 * the game, and is different even in different versions of the emc
440 * v4/v5 time is converted to 10x old time (as it should be).
441 * the reason the kingsoft player used 5x time was copy protection.
443 * note: emc v6 converter has an error in converting v4 eaters to the
444 * wrong bug(24 instead of 20) and tank(12 instead of 8).
447 /* changes for game engine integration in Rocks'n'Diamonds:
449 * cave versions below V5 had no grass, but only sand/dirt
450 * - object code 130 (V6 grass) is changed to 189 (V6 dirt)
451 * - object codes are changed in both cave and eater arrays
452 * - only graphical change, as both objects behave the same
454 * acid with no base beneath it is converted to fake acid
455 * - required for downunder mine 16, level 0 (and others)
458 static const unsigned char map_v6[256] =
462 0,0,2,2, 4,4,118,118, 8,9,10,11, 12,13,14,15,
463 16,16,18,18, 20,21,22,23, 24,25,26,27, 28,28,118,28,
464 0,16,2,18, 36,37,37,37, 40,41,42,43, 44,45,128,128,
465 128,148,148, 148,45,45,45, 148,0,57,58, 59,60,61,62,63,
467 64,65,66,67, 68,69,69,71, 72,73,74,75, 118,75,75,75,
468 75,75,75,75, 75,153,153,153, 153,153,153,153, 153,153,153,153,
469 153,153,153,99, 100,68,68,68, 68,68,68,68, 68,118,118,118,
470 118,118,114,115, 131,118,118,119, 120,121,122,118, 118,118,118,118,
472 128,129,130,131, 132,133,134,135, 136,137,138,139, 140,141,142,143,
473 144,145,146,147, 148,149,150,151, 152,153,154,155, 156,157,158,159,
474 160,161,162,163, 164,165,165,118, 168,169,170,171, 172,173,174,175,
475 176,177,178,179, 180,181,182,183, 184,185,186,187, 188,189,68,191,
477 192,193,194,195, 196,197,198,199, 200,201,202,203, 204,205,206,207,
478 208,209,210,211, 212,213,214,215, 216,217,218,219, 220,221,222,223,
479 224,225,226,227, 228,229,230,231, 232,233,234,235, 236,237,238,239,
480 240,241,242,243, 244,245,153,153, 153,153,153,153, 153,153,153,153
483 static const unsigned char map_v5[256] =
487 0,0,2,2, 4,4,118,118, 8,9,10,11, 12,13,14,15,
488 16,16,18,18, 20,21,22,23, 24,25,26,27, 28,28,118,28,
489 0,16,2,18, 36,37,37,37, 147,41,42,43, 44,45,128,128,
490 128,148,148,148, 45,45,45,148, 0,57,58,59, 60,61,62,63,
492 64,65,66,67, 68,153,153,153, 153,153,153,153, 153,153,153,153,
493 153,153,153,153, 153,153,153,153, 153,153,153,153, 153,153,153,153,
494 153,153,153,153, 153,68,68,68, 68,68,68,68, 68,118,118,118,
495 118,118,114,115, 131,118,118,119, 120,121,122,118, 118,118,118,118,
497 128,129,130,131, 132,133,134,135, 136,137,138,139, 140,141,142,143,
498 144,145,146,147, 148,149,150,151, 152,153,154,155, 156,157,158,159,
499 160,153,153,153, 153,153,153,118, 168,169,170,171, 172,173,174,175,
500 176,177,178,179, 180,181,182,183, 184,185,186,187, 188,189,68,153,
502 153,153,153,153, 153,153,153,153, 200,201,202,203, 204,205,206,207,
503 208,209,210,211, 212,213,214,215, 216,217,218,219, 220,221,222,223,
504 224,225,226,227, 228,229,230,231, 232,233,234,235, 236,237,238,239,
505 240,241,153,153, 153,153,153,153, 153,153,153,153, 153,153,153,153
508 static const unsigned char map_v4[256] =
512 0,0,2,2, 4,4,118,118, 8,9,10,11, 12,13,14,15,
513 16,16,18,18, 20,21,22,23, 24,25,26,27, 28,28,118,28,
514 0,16,2,18, 36,37,37,37, 147,41,42,43, 44,45,128,128,
515 128,148,148,148, 45,45,45,148, 0,153,153,59, 60,61,62,63,
517 64,65,66,153, 153,153,153,153, 153,153,153,153, 153,153,153,153,
518 153,153,153,153, 153,153,153,153, 153,153,153,153, 153,153,153,153,
519 153,153,153,153, 153,153,153,153, 153,153,153,153, 153,153,153,153,
520 153,118,114,115, 131,118,118,119, 120,121,122,118, 118,118,118,118,
522 128,129,189,131, 132,133,134,135, 136,137,138,139, 140,141,142,143,
523 144,145,146,147, 148,149,150,151, 152,68,154,155, 156,157,158,160,
524 160,160,160,160, 160,160,160,160, 160,160,160,160, 160,160,160,175,
525 153,153,153,153, 153,153,153,153, 153,153,153,153, 153,153,68,153,
527 153,153,153,153, 153,153,153,153, 200,201,202,203, 204,205,206,207,
528 208,209,210,211, 212,213,214,215, 216,217,218,219, 220,221,222,223,
529 224,225,226,227, 228,229,230,231, 232,233,234,235, 236,237,238,239,
530 240,241,153,153, 153,153,153,153, 153,153,153,153, 153,153,153,153
533 static const unsigned char map_v4_eater[32] =
535 /* filter for v4 eater */
537 128,18,2,0, 4,8,16,20, 28,37,41,45, 189,129,131,132,
538 133,134,135,136, 146,147,175,65, 66,64,2,18, 128,128,128,128
541 static boolean filename_has_v1_format(char *filename)
543 char *basename = getBaseNamePtr(filename);
545 return (strlen(basename) == 3 &&
546 basename[0] == 'a' &&
547 basename[1] >= 'a' && basename[1] <= 'k' &&
548 basename[2] >= '0' && basename[2] <= '9');
551 int cleanup_em_level(unsigned char *src, int length, char *filename)
553 int file_version = FILE_VERSION_EM_UNKNOWN;
556 if (length >= 2172 &&
557 src[2106] == 255 && /* version id: */
558 src[2107] == 54 && /* '6' */
559 src[2108] == 48 && /* '0' */
560 src[2109] == 48) /* '0' */
562 /* ---------- this cave has V6 file format ---------- */
563 file_version = FILE_VERSION_EM_V6;
565 /* remap elements to internal EMC level format */
566 for (i = 0; i < 2048; i++) /* cave */
567 src[i] = map_v6[src[i]];
568 for (i = 2048; i < 2084; i++) /* eaters */
569 src[i] = map_v6[src[i]];
570 for (i = 2112; i < 2148; i++) /* eaters */
571 src[i] = map_v6[src[i]];
573 else if (length >= 2110 &&
574 src[2106] == 255 && /* version id: */
575 src[2107] == 53 && /* '5' */
576 src[2108] == 48 && /* '0' */
577 src[2109] == 48) /* '0' */
579 /* ---------- this cave has V5 file format ---------- */
580 file_version = FILE_VERSION_EM_V5;
582 /* remap elements to internal EMC level format */
583 for (i = 0; i < 2048; i++) /* cave */
584 src[i] = map_v5[src[i]];
585 for (i = 2048; i < 2084; i++) /* eaters */
586 src[i] = map_v5[src[i]];
587 for (i = 2112; i < 2148; i++) /* eaters */
588 src[i] = src[i - 64];
590 else if (length >= 2106 &&
591 (src[1983] == 27 || /* encrypted (only EM I/II/III) */
592 src[1983] == 116 || /* unencrypted (usual case) */
593 src[1983] == 131)) /* unencrypted (rare case) */
595 /* ---------- this cave has V1, V2 or V3 file format ---------- */
597 boolean fix_copyright = FALSE;
600 byte at position 1983 (0x07bf) is used as "magic byte":
601 - 27 (0x1b) => encrypted level (V3 only / Kingsoft original games)
602 - 116 (0x74) => unencrypted level (byte is corrected to 131 (0x83))
603 - 131 (0x83) => unencrypted level (happens only in very rare cases)
606 if (src[1983] == 27) /* (0x1b) -- after decryption: 116 (0x74) */
608 /* this is original (encrypted) Emerald Mine I, II or III level file */
610 int first_byte = src[0];
611 unsigned char code0 = 0x65;
612 unsigned char code1 = 0x11;
614 /* decode encrypted level data */
615 for (i = 0; i < 2106; i++)
620 code0 = (code0 + 7) & 0xff;
623 src[1] = 131; /* needed for all Emerald Mine levels */
625 /* first byte is either 0xf1 (EM I and III) or 0xf5 (EM II) */
626 if (first_byte == 0xf5)
628 src[0] = 131; /* only needed for Emerald Mine II levels */
630 fix_copyright = TRUE;
633 /* ---------- this cave has V3 file format ---------- */
634 file_version = FILE_VERSION_EM_V3;
636 else if (filename_has_v1_format(filename))
638 /* ---------- this cave has V1 file format ---------- */
639 file_version = FILE_VERSION_EM_V1;
643 /* ---------- this cave has V2 file format ---------- */
644 file_version = FILE_VERSION_EM_V2;
647 /* remap elements to internal EMC level format */
648 for (i = 0; i < 2048; i++) /* cave */
649 src[i] = map_v4[src[i]];
650 for (i = 2048; i < 2084; i++) /* eaters */
651 src[i] = map_v4_eater[src[i] % 32];
652 for (i = 2112; i < 2148; i++) /* eaters */
653 src[i] = src[i - 64];
655 if (fix_copyright) /* fix "(c)" sign in Emerald Mine II levels */
657 for (i = 0; i < 2048; i++)
659 src[i] = 254; /* replace 'Cdecor_1' with 'Calpha_copyr' */
664 /* ---------- this cave has unknown file format ---------- */
666 /* if file has length of old-style level file, print (wrong) magic byte */
668 Error(ERR_WARN, "unknown magic byte 0x%02x at position 0x%04x",
671 return FILE_VERSION_EM_UNKNOWN;
674 if (file_version < FILE_VERSION_EM_V6)
677 src[2106] = 255; /* version id: */
678 src[2107] = 54; /* '6' */
679 src[2108] = 48; /* '0' */
680 src[2109] = 48; /* '0' */
684 /* stored level time of levels for the V2 player was changed to 50% of the
685 time for the V1 player (original V3 levels already considered this) */
686 if (file_version != FILE_VERSION_EM_V1 &&
687 file_version != FILE_VERSION_EM_V3)
692 for (i = 2148; i < 2172; i++)
699 /* ---------- at this stage, the cave data always has V6 format ---------- */
702 for (i = 0; i < 2048; i++)
705 for (i++; i < 2048; i++)
710 for (i = 64; i < 2048; i++)
711 if (src[i] == 63) /* replace element above 'Cacid_s' ... */
712 src[i - 64] = 101; /* ... with 'Cacid_1' */
714 /* fix acid with no base beneath it (see comment above for details) */
715 for (i = 64; i < 2048 - 1; i++)
717 if (file_version <= FILE_VERSION_EM_V2 &&
718 src[i - 64] == 101 && src[i] != 63) /* acid without base */
720 if (src[i - 1] == 101 || /* remove acid over acid row */
722 src[i - 64] = 6; /* replace element above with 'Cblank' */
724 src[i - 64] = 255; /* replace element above with 'Cfake_acid_1' */
728 /* fix acid in eaters */
729 for (i = 0; i < 8; i++)
730 for (j = 0; j < 6; j++)
731 if (src[eater_offset[i] + j + 3] == 63)
732 src[eater_offset[i] + j] = 101;
737 /* set cave tile at player position to blank */
738 for (i = 0; i < 2; i++)
739 src[GET_BE16(src[2096 + i * 2]) % 2048] = 128;
749 src[2159] = map_v6[src[2159]];
759 /* size of v6 cave */
763 Error(ERR_DEBUG, "EM level file version: %d", file_version);
772 structure of emerald mine level disk files
773 ----------------------------------------------------------------------
775 if(len >= 2172 && (buf[2106] == 255 && buf[2107] == 54 && buf[2108] == 48 && buf[2109] == 48)) // v6
776 if(len >= 2110 && (buf[2106] == 255 && buf[2107] == 53 && buf[2108] == 48 && buf[2109] == 48)) // v5
777 if(len >= 2106 && (buf[1983] == 116 || buf[2047] == 116)) // v4
778 if(len >= 2106 && (buf[1983] == 27 || buf[2047] == 219)) // v3
780 buf[0]=241;buf[1]=248;for(i=0,j=101;i<2106;i++,j+=7)buf[i]=(buf[i]^j)-17; // decrypt
782 number of movements (calls to logic) = time * 50 / 8
784 {} reserved (but some broken levels use them)
786 ----------------------------------------------------------------------
806 2095: emeralds needed
810 2102: wonderwall time
812 2106: ID (0xff363030)
818 2148: flags bit#7=NOI #6=RIS
819 2149: wind direction bit#0=right #1=down #2=left #3=up
820 2150: cave number bit#7=teamwork
829 2162: ball info bit#15=switch state #8=random
830 ; bit#0=N #1=S #2=W #3=E #4=SE #5=SW #6=NE #7=NW
831 2164: android move speed
832 2166: android clone speed
834 ; bit#0=emerald #1=diamond #2=stone #3=bomb #4=nut #5=tank #6=eater
835 ; #7=bug #8=alien #9=spring #10=balloon #11=ameuba #12=dynamite
840 1: stone {stone_fall}
842 3: diamond {diamond_fall}
844 5: alien {alien_pause}
858 19: emerald {emerald_fall}
869 30: blank {drip_stretchB}
870 31: drip {drip_stretch}
871 32: stone {stone_pause}
872 33: bomb {bomb_pause}
873 34: diamond {diamond_pause}
874 35: emerald {emerald_pause}
875 36: wonderwall {wonderwallB}
885 46: blank {sand_stonein_2}
886 47: blank {sand_stonein_3}
887 48: blank {sand_stonein_4}
888 49: sand {sand_stonesand_2}
889 50: sand {sand_stonesand_3}
890 51: sand {sand_stonesand_4}
891 52: sand_stone {sand_sandstone_2}
892 53: sand_stone {sand_sandstone_3}
893 54: sand_stone {sand_sandstone_4}
894 55: sand {sand_stonesand_4}
895 56: stone {sand_stoneout_2}
909 70: spring {spring_fall}
910 71: spring {spring_w}
911 72: spring {spring_e}
916 77: android {android_n_1}
917 78: android {android_n_2}
918 79: android {android_s_1}
919 80: android {android_s_2}
920 81: android {android_e_1}
921 82: android {android_e_2}
922 83: android {android_w_1}
923 84: android {android_w_2}
938 99: spring {push_spring_w}
939 100: spring {push_spring_e}
948 109: pause {grass_wB}
949 110: pause {grass_eB}
950 111: pause {grass_nB}
951 112: pause {grass_sB}
952 113: pause {dynamite_blank}
953 114: nut {push_nut_w}
954 115: nut {push_nut_e}
955 116: steel_2 {end of level}
957 118: pause {emerald_blank}
958 119: bomb {push_bomb_w}
959 120: bomb {push_bomb_e}
960 121: stone {push_stone_w}
961 122: stone {push_stone_e}
962 123: pause {diamond_blank}
1003 163: fake_blank {fake_blankB}
1004 164: fake_grass {fake_grassB}
1006 166: switch {switchB}
1097 ----------------------------------------------------------------------
1113 2091: dynamite value
1117 2095: emeralds needed
1121 2102: wonderwall time
1123 2106: ID (0xff353030)
1127 1: stone {stone_fall}
1129 3: diamond {diamond_fall}
1131 5: alien {alien_pause}
1143 17: bomb {bomb_fall}
1145 19: emerald {emerald_fall}
1155 29: drip {drip_fall}
1156 30: blank {drip_stretchB}
1157 31: drip {drip_stretch}
1158 32: stone {stone_pause}
1159 33: bomb {bomb_pause}
1160 34: diamond {diamond_pause}
1161 35: emerald {emerald_pause}
1162 36: wonderwall {wonderwallB}
1172 46: blank {sand_stonein_2}
1173 47: blank {sand_stonein_3}
1174 48: blank {sand_stonein_4}
1175 49: sand {sand_stonesand_2}
1176 50: sand {sand_stonesand_3}
1177 51: sand {sand_stonesand_4}
1178 52: sand_stone {sand_sandstone_2}
1179 53: sand_stone {sand_sandstone_3}
1180 54: sand_stone {sand_sandstone_4}
1181 55: sand {sand_stonesand_4}
1182 56: stone {sand_stoneout_2}
1235 109: pause {grass_wB}
1236 110: pause {grass_eB}
1237 111: pause {grass_nB}
1238 112: pause {grass_sB}
1239 113: pause {dynamite_blank}
1240 114: nut {push_nut_w}
1241 115: nut {push_nut_e}
1242 116: steel_2 {end of level}
1243 117: dynamite_4 {boom_2}
1244 118: pause {emerald_blank}
1245 119: bomb {push_bomb_w}
1246 120: bomb {push_bomb_e}
1247 121: stone {push_stone_w}
1248 122: stone {push_stone_e}
1249 123: pause {diamond_blank}
1250 124: pause {dirt_wB}
1251 125: pause {dirt_eB}
1252 126: pause {dirt_nB}
1253 127: pause {dirt_sB}
1384 ----------------------------------------------------------------------
1400 2091: dynamite value
1404 2095: emeralds needed
1408 2102: wonderwall time
1438 26: diamond {diamond_shine}
1439 27: emerald {emerald_shine}
1442 1: stone {stone_fall}
1444 3: diamond {diamond_fall}
1446 5: alien {alien_pause}
1458 17: bomb {bomb_fall}
1460 19: emerald {emerald_fall}
1470 29: drip {drip_fall}
1471 30: blank {drip_stretchB}
1472 31: drip {drip_stretch}
1473 32: stone {stone_pause}
1474 33: bomb {bomb_pause}
1475 34: diamond {diamond_pause}
1476 35: emerald {emerald_pause}
1477 36: wonderwall {wonderwallB}
1487 46: blank {sand_stonein_2}
1488 47: blank {sand_stonein_3}
1489 48: blank {sand_stonein_4}
1490 49: sand {sand_stonesand_2}
1491 50: sand {sand_stonesand_3}
1492 51: sand {sand_stonesand_4}
1493 52: sand_stone {sand_sandstone_2}
1494 53: sand_stone {sand_sandstone_3}
1495 54: sand_stone {sand_sandstone_4}
1496 55: sand {sand_stonesand_4}
1497 56: stone {sand_stoneout_2}
1554 113: pause {dynamite_blank}
1555 114: nut {push_nut_w}
1556 115: nut {push_nut_e}
1557 116: steel_1 {end of level}
1558 117: dynamite_4 {boom_2}
1559 118: pause {emerald_blank}
1560 119: bomb {push_bomb_w}
1561 120: bomb {push_bomb_e}
1562 121: stone {push_stone_w}
1563 122: stone {push_stone_e}
1564 123: pause {diamond_blank}
1565 124: pause {dirt_wB}
1566 125: pause {dirt_eB}
1567 126: pause {dirt_nB}
1568 127: pause {dirt_sB}
1601 159: fake_grass {dirt}
1602 160: fake_grass {dirt}
1603 161: fake_grass {dirt}
1604 162: fake_grass {dirt}
1605 163: fake_grass {dirt}
1606 164: fake_grass {dirt}
1607 165: fake_grass {dirt}
1608 166: fake_grass {dirt}
1609 167: fake_grass {dirt}
1610 168: fake_grass {dirt}
1611 169: fake_grass {dirt}
1612 170: fake_grass {dirt}
1613 171: fake_grass {dirt}
1614 172: fake_grass {dirt}
1615 173: fake_grass {dirt}
1616 174: fake_grass {dirt}
1682 240: alpha_arrow_e {}
1683 241: decor_1 {alpha_copyr}
1699 ----------------------------------------------------------------------