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 static const short map_emc[256] =
45 Xstone, Xstone, Xdiamond, Xdiamond,
46 Xalien, Xalien, Xblank, Xblank,
47 Xtank_1_n, Xtank_1_e, Xtank_1_s, Xtank_1_w,
48 Xtank_2_n, Xtank_2_e, Xtank_2_s, Xtank_2_w,
50 Xbomb, Xbomb, Xemerald, Xemerald,
51 Xbug_1_n, Xbug_1_e, Xbug_1_s, Xbug_1_w,
52 Xbug_2_n, Xbug_2_e, Xbug_2_s, Xbug_2_w,
53 Xdrip, Xdrip, Xdrip, Xdrip,
55 Xstone, Xbomb, Xdiamond, Xemerald,
56 Xwonderwall, Xnut, Xnut, Xnut,
57 Xwheel, Xeater_n, Xeater_s, Xeater_w,
58 Xeater_e, Xsand_stone, Xblank, Xblank,
60 Xblank, Xsand, Xsand, Xsand,
61 Xsand_stone, Xsand_stone, Xsand_stone, Xsand,
62 Xstone, Xslide_ew, Xslide_ns, Xdynamite_1,
63 Xdynamite_2, Xdynamite_3, Xdynamite_4, Xacid_s,
65 Xexit_1, Xexit_2, Xexit_3, Xballoon,
66 Xplant, Xspring, Xspring_fall, Xspring_w,
67 Xspring_e, Xball_1, Xball_2, Xandroid,
68 Xblank, Xandroid, Xandroid, Xandroid,
70 Xandroid, Xandroid, Xandroid, Xandroid,
71 Xandroid, Xblank, Xblank, Xblank,
72 Xblank, Xblank, Xblank, Xblank,
73 Xblank, Xblank, Xblank, Xblank,
75 Xblank, Xblank, Xblank, Xpush_spring_w,
76 Xpush_spring_e, Xacid_1, Xacid_2, Xacid_3,
77 Xacid_4, Xacid_5, Xacid_6, Xacid_7,
78 Xacid_8, Xblank, Xblank, Xblank,
80 Xblank, Xblank, Xpush_nut_w, Xpush_nut_e,
81 Xsteel_1, Xblank, Xblank, Xpush_bomb_w,
82 Xpush_bomb_e, Xpush_stone_w, Xpush_stone_e, Xblank,
83 Xblank, Xblank, Xblank, Xblank,
85 Xblank, Xroundwall_1, Xgrass, Xsteel_1,
86 Xwall_1, Xkey_1, Xkey_2, Xkey_3,
87 Xkey_4, Xdoor_1, Xdoor_2, Xdoor_3,
88 Xdoor_4, Xfake_amoeba, Xfake_door_1, Xfake_door_2,
90 Xfake_door_3, Xfake_door_4, Xwonderwall, Xwheel,
91 Xsand, Xacid_nw, Xacid_ne, Xacid_sw,
92 Xacid_se, Xfake_blank, Xamoeba_1, Xamoeba_2,
93 Xamoeba_3, Xamoeba_4, Xexit, Xalpha_arrow_w,
95 Xfake_grass, Xlenses, Xmagnify, Xfake_blank,
96 Xfake_grass, Xswitch, Xswitch, Xblank,
97 Xdecor_8, Xdecor_9, Xdecor_10, Xdecor_5,
98 Xalpha_comma, Xalpha_quote, Xalpha_minus, Xdynamite,
100 Xsteel_3, Xdecor_6, Xdecor_7, Xsteel_2,
101 Xroundwall_2, Xdecor_2, Xdecor_4, Xdecor_3,
102 Xwind_any, Xwind_e, Xwind_s, Xwind_w,
103 Xwind_n, Xdirt, Xplant, Xkey_5,
105 Xkey_6, Xkey_7, Xkey_8, Xdoor_5,
106 Xdoor_6, Xdoor_7, Xdoor_8, Xbumper,
107 Xalpha_a, Xalpha_b, Xalpha_c, Xalpha_d,
108 Xalpha_e, Xalpha_f, Xalpha_g, Xalpha_h,
110 Xalpha_i, Xalpha_j, Xalpha_k, Xalpha_l,
111 Xalpha_m, Xalpha_n, Xalpha_o, Xalpha_p,
112 Xalpha_q, Xalpha_r, Xalpha_s, Xalpha_t,
113 Xalpha_u, Xalpha_v, Xalpha_w, Xalpha_x,
115 Xalpha_y, Xalpha_z, Xalpha_0, Xalpha_1,
116 Xalpha_2, Xalpha_3, Xalpha_4, Xalpha_5,
117 Xalpha_6, Xalpha_7, Xalpha_8, Xalpha_9,
118 Xalpha_perio, Xalpha_excla, Xalpha_colon, Xalpha_quest,
120 Xalpha_arrow_e, Xdecor_1, Xfake_door_5, Xfake_door_6,
121 Xfake_door_7, Xfake_door_8, Xblank, Xblank,
122 Xblank, Xblank, Xblank, Xblank,
123 Xblank, Xblank, Xalpha_copyr, Xfake_acid_1
126 static int get_em_element(unsigned short em_element_raw, int file_version)
128 int em_element = map_emc[em_element_raw];
130 if (file_version < FILE_VERSION_EM_V5)
132 /* versions below V5 had no grass, but only sand/dirt */
133 if (em_element == Xgrass)
140 void convert_em_level(unsigned char *src, int file_version)
142 static int eater_offset[8] =
144 0x800, 0x809, 0x812, 0x81B, 0x840, 0x849, 0x852, 0x85B
148 lev.time_seconds = src[0x83E] << 8 | src[0x83F];
149 if (lev.time_seconds > 9999)
150 lev.time_seconds = 9999;
152 lev.required_initial = src[0x82F];
154 for (i = 0; i < 2; i++)
156 temp = src[0x830 + i * 2] << 8 | src[0x831 + i * 2];
157 ply[i].x_initial = (temp & 63);
158 ply[i].y_initial = (temp >> 6 & 31);
161 temp = (src[0x834] << 8 | src[0x835]) * 28;
164 lev.amoeba_time = temp;
166 lev.android_move_time = src[0x874] << 8 | src[0x875];
167 lev.android_clone_time = src[0x876] << 8 | src[0x877];
169 lev.ball_random = src[0x872] & 1 ? 1 : 0;
170 lev.ball_state_initial = src[0x872] & 128 ? 1 : 0;
171 lev.ball_time = src[0x870] << 8 | src[0x871];
173 lev.emerald_score = src[0x824];
174 lev.diamond_score = src[0x825];
175 lev.alien_score = src[0x826];
176 lev.tank_score = src[0x827];
177 lev.bug_score = src[0x828];
178 lev.eater_score = src[0x829];
179 lev.nut_score = src[0x82A];
180 lev.dynamite_score = src[0x82B];
181 lev.key_score = src[0x82C];
182 lev.exit_score = src[0x82D] * 8 / 5;
183 lev.lenses_score = src[0x867];
184 lev.magnify_score = src[0x868];
185 lev.slurp_score = src[0x869];
187 lev.lenses_time = src[0x86A] << 8 | src[0x86B];
188 lev.magnify_time = src[0x86C] << 8 | src[0x86D];
189 lev.wheel_time = src[0x838] << 8 | src[0x839];
191 lev.wind_cnt_initial = src[0x865] & 15 ? lev.wind_time : 0;
193 lev.wind_direction_initial = (temp & 8 ? 0 :
198 lev.wonderwall_time_initial = src[0x836] << 8 | src[0x837];
200 for (i = 0; i < 8; i++)
201 for (x = 0; x < 9; x++)
202 lev.eater_array[i][x] =
203 get_em_element(src[eater_offset[i] + x], file_version);
205 temp = get_em_element(src[0x86F], file_version);
206 for (y = 0; y < 8; y++)
210 for (x = 0; x < 8; x++)
211 lev.ball_array[y][x] = temp;
215 lev.ball_array[y][1] = (src[0x873] & 1) ? temp : Xblank; /* north */
216 lev.ball_array[y][6] = (src[0x873] & 2) ? temp : Xblank; /* south */
217 lev.ball_array[y][3] = (src[0x873] & 4) ? temp : Xblank; /* west */
218 lev.ball_array[y][4] = (src[0x873] & 8) ? temp : Xblank; /* east */
219 lev.ball_array[y][7] = (src[0x873] & 16) ? temp : Xblank; /* southeast */
220 lev.ball_array[y][5] = (src[0x873] & 32) ? temp : Xblank; /* southwest */
221 lev.ball_array[y][2] = (src[0x873] & 64) ? temp : Xblank; /* northeast */
222 lev.ball_array[y][0] = (src[0x873] & 128)? temp : Xblank; /* northwest */
226 temp = src[0x878] << 8 | src[0x879];
230 lev.android_array[Xemerald] = Xemerald;
231 lev.android_array[Xemerald_pause] = Xemerald;
232 lev.android_array[Xemerald_fall] = Xemerald;
233 lev.android_array[Yemerald_sB] = Xemerald;
234 lev.android_array[Yemerald_eB] = Xemerald;
235 lev.android_array[Yemerald_wB] = Xemerald;
240 lev.android_array[Xdiamond] = Xdiamond;
241 lev.android_array[Xdiamond_pause] = Xdiamond;
242 lev.android_array[Xdiamond_fall] = Xdiamond;
243 lev.android_array[Ydiamond_sB] = Xdiamond;
244 lev.android_array[Ydiamond_eB] = Xdiamond;
245 lev.android_array[Ydiamond_wB] = Xdiamond;
250 lev.android_array[Xstone] = Xstone;
251 lev.android_array[Xstone_pause] = Xstone;
252 lev.android_array[Xstone_fall] = Xstone;
253 lev.android_array[Ystone_sB] = Xstone;
254 lev.android_array[Ystone_eB] = Xstone;
255 lev.android_array[Ystone_wB] = Xstone;
260 lev.android_array[Xbomb] = Xbomb;
261 lev.android_array[Xbomb_pause] = Xbomb;
262 lev.android_array[Xbomb_fall] = Xbomb;
263 lev.android_array[Ybomb_sB] = Xbomb;
264 lev.android_array[Ybomb_eB] = Xbomb;
265 lev.android_array[Ybomb_wB] = Xbomb;
270 lev.android_array[Xnut] = Xnut;
271 lev.android_array[Xnut_pause] = Xnut;
272 lev.android_array[Xnut_fall] = Xnut;
273 lev.android_array[Ynut_sB] = Xnut;
274 lev.android_array[Ynut_eB] = Xnut;
275 lev.android_array[Ynut_wB] = Xnut;
280 lev.android_array[Xtank_1_n] = Xtank_1_n;
281 lev.android_array[Xtank_2_n] = Xtank_1_n;
282 lev.android_array[Ytank_nB] = Xtank_1_n;
283 lev.android_array[Ytank_n_e] = Xtank_1_n;
284 lev.android_array[Ytank_n_w] = Xtank_1_n;
286 lev.android_array[Xtank_1_e] = Xtank_1_e;
287 lev.android_array[Xtank_2_e] = Xtank_1_e;
288 lev.android_array[Ytank_eB] = Xtank_1_e;
289 lev.android_array[Ytank_e_s] = Xtank_1_e;
290 lev.android_array[Ytank_e_n] = Xtank_1_e;
292 lev.android_array[Xtank_1_s] = Xtank_1_s;
293 lev.android_array[Xtank_2_s] = Xtank_1_s;
294 lev.android_array[Ytank_sB] = Xtank_1_s;
295 lev.android_array[Ytank_s_w] = Xtank_1_s;
296 lev.android_array[Ytank_s_e] = Xtank_1_s;
298 lev.android_array[Xtank_1_w] = Xtank_1_w;
299 lev.android_array[Xtank_2_w] = Xtank_1_w;
300 lev.android_array[Ytank_wB] = Xtank_1_w;
301 lev.android_array[Ytank_w_n] = Xtank_1_w;
302 lev.android_array[Ytank_w_s] = Xtank_1_w;
307 lev.android_array[Xeater_n] = Xeater_n;
308 lev.android_array[Yeater_nB] = Xeater_n;
310 lev.android_array[Xeater_e] = Xeater_e;
311 lev.android_array[Yeater_eB] = Xeater_e;
313 lev.android_array[Xeater_s] = Xeater_s;
314 lev.android_array[Yeater_sB] = Xeater_s;
316 lev.android_array[Xeater_w] = Xeater_w;
317 lev.android_array[Yeater_wB] = Xeater_w;
322 lev.android_array[Xbug_1_n] = Xbug_2_n;
323 lev.android_array[Xbug_2_n] = Xbug_2_n;
324 lev.android_array[Ybug_nB] = Xbug_2_n;
325 lev.android_array[Ybug_n_e] = Xbug_2_n;
326 lev.android_array[Ybug_n_w] = Xbug_2_n;
328 lev.android_array[Xbug_1_e] = Xbug_2_e;
329 lev.android_array[Xbug_2_e] = Xbug_2_e;
330 lev.android_array[Ybug_eB] = Xbug_2_e;
331 lev.android_array[Ybug_e_s] = Xbug_2_e;
332 lev.android_array[Ybug_e_n] = Xbug_2_e;
334 lev.android_array[Xbug_1_s] = Xbug_2_s;
335 lev.android_array[Xbug_2_s] = Xbug_2_s;
336 lev.android_array[Ybug_sB] = Xbug_2_s;
337 lev.android_array[Ybug_s_w] = Xbug_2_s;
338 lev.android_array[Ybug_s_e] = Xbug_2_s;
340 lev.android_array[Xbug_1_w] = Xbug_2_w;
341 lev.android_array[Xbug_2_w] = Xbug_2_w;
342 lev.android_array[Ybug_wB] = Xbug_2_w;
343 lev.android_array[Ybug_w_n] = Xbug_2_w;
344 lev.android_array[Ybug_w_s] = Xbug_2_w;
349 lev.android_array[Xalien] = Xalien;
350 lev.android_array[Xalien_pause] = Xalien;
351 lev.android_array[Yalien_nB] = Xalien;
352 lev.android_array[Yalien_eB] = Xalien;
353 lev.android_array[Yalien_sB] = Xalien;
354 lev.android_array[Yalien_wB] = Xalien;
359 lev.android_array[Xspring] = Xspring;
360 lev.android_array[Xspring_pause] = Xspring;
361 lev.android_array[Xspring_e] = Xspring;
362 lev.android_array[Yspring_eB] = Xspring;
363 lev.android_array[Yspring_alien_eB] = Xspring;
364 lev.android_array[Xspring_w] = Xspring;
365 lev.android_array[Yspring_wB] = Xspring;
366 lev.android_array[Yspring_alien_wB] = Xspring;
367 lev.android_array[Xspring_fall] = Xspring;
368 lev.android_array[Yspring_sB] = Xspring;
373 lev.android_array[Yballoon_nB] = Xballoon;
374 lev.android_array[Yballoon_eB] = Xballoon;
375 lev.android_array[Yballoon_sB] = Xballoon;
376 lev.android_array[Yballoon_wB] = Xballoon;
377 lev.android_array[Xballoon] = Xballoon;
382 lev.android_array[Xfake_amoeba] = Xdrip;
383 lev.android_array[Yfake_amoeba] = Xdrip;
384 lev.android_array[Xamoeba_1] = Xdrip;
385 lev.android_array[Xamoeba_2] = Xdrip;
386 lev.android_array[Xamoeba_3] = Xdrip;
387 lev.android_array[Xamoeba_4] = Xdrip;
388 lev.android_array[Xamoeba_5] = Xdrip;
389 lev.android_array[Xamoeba_6] = Xdrip;
390 lev.android_array[Xamoeba_7] = Xdrip;
391 lev.android_array[Xamoeba_8] = Xdrip;
396 lev.android_array[Xdynamite] = Xdynamite;
399 for (temp = 1; temp < 2047; temp++)
403 case 0x24: /* wonderwall */
404 lev.wonderwall_state_initial = 1;
405 lev.wonderwall_time_initial = 9999;
408 case 0x28: /* wheel */
409 lev.wheel_x_initial = temp & 63;
410 lev.wheel_y_initial = temp >> 6;
411 lev.wheel_cnt_initial = lev.wheel_time;
414 case 0xA3: /* fake blank */
415 lev.lenses_cnt_initial = 9999;
418 case 0xA4: /* fake grass */
419 lev.magnify_cnt_initial = 9999;
424 /* first fill the complete playfield with the default border element */
425 for (y = 0; y < CAVE_HEIGHT; y++)
426 for (x = 0; x < CAVE_WIDTH; x++)
427 native_em_level.cave[x][y] = Zborder;
429 /* then copy the real level contents from level file into the playfield */
431 for (y = 0; y < lev.height; y++)
432 for (x = 0; x < lev.width; x++)
433 native_em_level.cave[x][y] =
434 get_em_element(src[temp++], file_version);
436 /* at last, set the two players at their positions in the playfield */
437 /* (native EM[C] levels always have exactly two players in a level) */
438 for (i = 0; i < 2; i++)
439 native_em_level.cave[ply[i].x_initial][ply[i].y_initial] = Zplayer;
441 native_em_level.file_version = file_version;
444 void prepare_em_level(void)
450 /* reset all runtime variables to their initial values */
452 game_init_cave_buffers();
454 lev.left = CAVE_BUFFER_XOFFSET;
455 lev.top = CAVE_BUFFER_YOFFSET;
456 lev.right = lev.left + lev.width;
457 lev.bottom = lev.top + lev.height;
459 /* add linked cave buffer columns for wrap-around movement */
460 for (x = 0; x < lev.left; x++)
462 lev.cavecol[x] = lev.cavecol[lev.width + x];
463 lev.nextcol[x] = lev.nextcol[lev.width + x];
464 lev.drawcol[x] = lev.drawcol[lev.width + x];
465 lev.boomcol[x] = lev.boomcol[lev.width + x];
467 lev.cavecol[lev.right + x] = lev.cavecol[lev.left + x];
468 lev.nextcol[lev.right + x] = lev.nextcol[lev.left + x];
469 lev.drawcol[lev.right + x] = lev.drawcol[lev.left + x];
470 lev.boomcol[lev.right + x] = lev.boomcol[lev.left + x];
473 for (x = 0; x < lev.width; x++)
474 for (y = 0; y < lev.height; y++)
475 lev.cave[lev.left + x][lev.top + y] = native_em_level.cave[x][y];
477 for (x = lev.left; x < lev.right; x++)
478 for (y = lev.top; y < lev.bottom; y++)
479 lev.next[x][y] = lev.draw[x][y] = lev.cave[x][y];
481 lev.time_initial = lev.time_seconds;
482 lev.time = lev.time_initial;
484 lev.required = lev.required_initial;
487 lev.android_move_cnt = lev.android_move_time;
488 lev.android_clone_cnt = lev.android_clone_time;
491 lev.ball_state = lev.ball_state_initial;
492 lev.ball_cnt = lev.ball_time;
497 lev.lenses_cnt = lev.lenses_cnt_initial;
498 lev.magnify_cnt = lev.magnify_cnt_initial;
500 lev.wheel_cnt = lev.wheel_cnt_initial;
501 lev.wheel_x = lev.wheel_x_initial;
502 lev.wheel_y = lev.wheel_y_initial;
504 lev.wind_direction = lev.wind_direction_initial;
505 lev.wind_cnt = lev.wind_cnt_initial;
507 lev.wonderwall_state = lev.wonderwall_state_initial;
508 lev.wonderwall_time = lev.wonderwall_time_initial;
510 lev.killed_out_of_time = FALSE;
512 /* determine number of players in this level */
513 lev.home_initial = 0;
515 for (i = 0; i < MAX_PLAYERS; i++)
518 ply[i].alive_initial = FALSE;
520 if (ply[i].x_initial != -1 && ply[i].y_initial != -1)
528 team_mode = getTeamMode_EM();
531 lev.home_initial = 1;
533 lev.home = lev.home_initial;
534 players_left = lev.home_initial;
536 for (i = 0; i < MAX_PLAYERS; i++)
542 ply[i].alive_initial = TRUE;
547 int x = ply[i].x_initial;
548 int y = ply[i].y_initial;
550 native_em_level.cave[x][y] = Xblank;
552 lev.cave[lev.left + x][lev.top + y] = Xblank;
553 lev.next[lev.left + x][lev.top + y] = Xblank;
554 lev.draw[lev.left + x][lev.top + y] = Xblank;
559 for (i = 0; i < MAX_PLAYERS; i++)
562 ply[i].alive = ply[i].alive_initial;
564 ply[i].dynamite_cnt = 0;
567 ply[i].oldx = ply[i].x = ply[i].x_initial + lev.left;
568 ply[i].oldy = ply[i].y = ply[i].y_initial + lev.top;
569 ply[i].last_move_dir = MV_NONE;
570 ply[i].joy_n = ply[i].joy_e = ply[i].joy_s = ply[i].joy_w = 0;
571 ply[i].joy_snap = ply[i].joy_drop = 0;
572 ply[i].joy_stick = ply[i].joy_spin = 0;
575 // the following engine variables are initialized to version-specific values
576 // in function InitGameEngine() (src/game.c):
578 // - game_em.use_single_button (default: TRUE)
579 // - game_em.use_snap_key_bug (default: FALSE)
581 game_em.level_solved = FALSE;
582 game_em.game_over = FALSE;
584 game_em.any_player_moving = FALSE;
585 game_em.any_player_snapping = FALSE;
587 game_em.last_moving_player = 0; /* default: first player */
589 for (i = 0; i < MAX_PLAYERS; i++)
590 game_em.last_player_direction[i] = MV_NONE;
592 lev.exit_x = lev.exit_y = -1; /* kludge for playing player exit sound */
596 /* convert all emerald mine caves to emc version 6 cave format.
598 * caves are filtered to get rid of invalid or unsupported tiles.
600 * although the result is a somewhat clean cave, it is meant only
601 * to give a common structure for the binary cave format. it is not
602 * for archiving purposes (it is better to keep the raw cave as-is)
603 * and it is not meant for serializing (the intermediate structure
604 * is better defined).
606 * acid top is added to acid bottom in both the cave and the eaters.
607 * fake acid (only in v4) does not exist because it adds nothing to
608 * the game, and is different even in different versions of the emc
611 * v4/v5 time is converted to 10x old time (as it should be).
612 * the reason the kingsoft player used 5x time was copy protection.
614 * note: emc v6 converter has an error in converting v4 eaters to the
615 * wrong bug(24 instead of 20) and tank(12 instead of 8).
618 static const unsigned char map_v6[256] =
622 0,0,2,2, 4,4,118,118, 8,9,10,11, 12,13,14,15,
623 16,16,18,18, 20,21,22,23, 24,25,26,27, 28,28,118,28,
624 0,16,2,18, 36,37,37,37, 40,41,42,43, 44,45,128,128,
625 128,148,148, 148,45,45,45, 148,0,57,58, 59,60,61,62,63,
627 64,65,66,67, 68,69,69,71, 72,73,74,75, 118,75,75,75,
628 75,75,75,75, 75,153,153,153, 153,153,153,153, 153,153,153,153,
629 153,153,153,99, 100,68,68,68, 68,68,68,68, 68,118,118,118,
630 118,118,114,115, 131,118,118,119, 120,121,122,118, 118,118,118,118,
632 128,129,130,131, 132,133,134,135, 136,137,138,139, 140,141,142,143,
633 144,145,146,147, 148,149,150,151, 152,153,154,155, 156,157,158,159,
634 160,161,162,163, 164,165,165,118, 168,169,170,171, 172,173,174,175,
635 176,177,178,179, 180,181,182,183, 184,185,186,187, 188,189,68,191,
637 192,193,194,195, 196,197,198,199, 200,201,202,203, 204,205,206,207,
638 208,209,210,211, 212,213,214,215, 216,217,218,219, 220,221,222,223,
639 224,225,226,227, 228,229,230,231, 232,233,234,235, 236,237,238,239,
640 240,241,242,243, 244,245,153,153, 153,153,153,153, 153,153,153,153
643 static const unsigned char map_v5[256] =
647 0,0,2,2, 4,4,118,118, 8,9,10,11, 12,13,14,15,
648 16,16,18,18, 20,21,22,23, 24,25,26,27, 28,28,118,28,
649 0,16,2,18, 36,37,37,37, 147,41,42,43, 44,45,128,128,
650 128,148,148,148, 45,45,45,148, 0,57,58,59, 60,61,62,63,
652 64,65,66,67, 68,153,153,153, 153,153,153,153, 153,153,153,153,
653 153,153,153,153, 153,153,153,153, 153,153,153,153, 153,153,153,153,
654 153,153,153,153, 153,68,68,68, 68,68,68,68, 68,118,118,118,
655 118,118,114,115, 131,118,118,119, 120,121,122,118, 118,118,118,118,
657 128,129,130,131, 132,133,134,135, 136,137,138,139, 140,141,142,143,
658 144,145,146,147, 148,149,150,151, 152,153,154,155, 156,157,158,159,
659 160,153,153,153, 153,153,153,118, 168,169,170,171, 172,173,174,175,
660 176,177,178,179, 180,181,182,183, 184,185,186,187, 188,189,68,153,
662 153,153,153,153, 153,153,153,153, 200,201,202,203, 204,205,206,207,
663 208,209,210,211, 212,213,214,215, 216,217,218,219, 220,221,222,223,
664 224,225,226,227, 228,229,230,231, 232,233,234,235, 236,237,238,239,
665 240,241,153,153, 153,153,153,153, 153,153,153,153, 153,153,153,153
668 static const unsigned char map_v4[256] =
672 0,0,2,2, 4,4,118,118, 8,9,10,11, 12,13,14,15,
673 16,16,18,18, 20,21,22,23, 24,25,26,27, 28,28,118,28,
674 0,16,2,18, 36,37,37,37, 147,41,42,43, 44,45,128,128,
675 128,148,148,148, 45,45,45,148, 0,153,153,59, 60,61,62,63,
677 64,65,66,153, 153,153,153,153, 153,153,153,153, 153,153,153,153,
678 153,153,153,153, 153,153,153,153, 153,153,153,153, 153,153,153,153,
679 153,153,153,153, 153,153,153,153, 153,153,153,153, 153,153,153,153,
680 153,118,114,115, 131,118,118,119, 120,121,122,118, 118,118,118,118,
682 128,129,130,131, 132,133,134,135, 136,137,138,139, 140,141,142,143,
683 144,145,146,147, 148,149,150,151, 152,68,154,155, 156,157,158,160,
684 160,160,160,160, 160,160,160,160, 160,160,160,160, 160,160,160,175,
685 153,153,153,153, 153,153,153,153, 153,153,153,153, 153,153,68,153,
687 153,153,153,153, 153,153,153,153, 200,201,202,203, 204,205,206,207,
688 208,209,210,211, 212,213,214,215, 216,217,218,219, 220,221,222,223,
689 224,225,226,227, 228,229,230,231, 232,233,234,235, 236,237,238,239,
690 240,241,153,153, 153,153,153,153, 153,153,153,153, 153,153,153,153
693 static const unsigned char map_v4_eater[32] =
695 /* filter for v4 eater */
697 128,18,2,0, 4,8,16,20, 28,37,41,45, 130,129,131,132,
698 133,134,135,136, 146,147,175,65, 66,64,2,18, 128,128,128,128
701 static boolean filename_has_v1_format(char *filename)
703 char *basename = getBaseNamePtr(filename);
705 return (strlen(basename) == 3 &&
706 basename[0] == 'a' &&
707 basename[1] >= 'a' && basename[1] <= 'k' &&
708 basename[2] >= '0' && basename[2] <= '9');
711 int cleanup_em_level(unsigned char *src, int length, char *filename)
713 int file_version = FILE_VERSION_EM_UNKNOWN;
716 if (length >= 2172 &&
717 src[2106] == 255 && /* version id: */
718 src[2107] == 54 && /* '6' */
719 src[2108] == 48 && /* '0' */
720 src[2109] == 48) /* '0' */
722 /* ---------- this cave has V6 file format ---------- */
723 file_version = FILE_VERSION_EM_V6;
725 /* remap elements to internal EMC level format */
726 for (i = 0; i < 2048; i++)
727 src[i] = map_v6[src[i]];
728 for (i = 2048; i < 2084; i++)
729 src[i] = map_v6[src[i]];
730 for (i = 2112; i < 2148; i++)
731 src[i] = map_v6[src[i]];
733 else if (length >= 2110 &&
734 src[2106] == 255 && /* version id: */
735 src[2107] == 53 && /* '5' */
736 src[2108] == 48 && /* '0' */
737 src[2109] == 48) /* '0' */
739 /* ---------- this cave has V5 file format ---------- */
740 file_version = FILE_VERSION_EM_V5;
742 /* remap elements to internal EMC level format */
743 for (i = 0; i < 2048; i++)
744 src[i] = map_v5[src[i]];
745 for (i = 2048; i < 2084; i++)
746 src[i] = map_v5[src[i]];
747 for (i = 2112; i < 2148; i++)
748 src[i] = src[i - 64];
750 else if (length >= 2106 &&
751 (src[1983] == 27 || /* encrypted (only EM I/II/III) */
752 src[1983] == 116 || /* unencrypted (usual case) */
753 src[1983] == 131)) /* unencrypted (rare case) */
755 /* ---------- this cave has V1, V2 or V3 file format ---------- */
757 boolean fix_copyright = FALSE;
760 byte at position 1983 (0x07bf) is used as "magic byte":
761 - 27 (0x1b) => encrypted level (V3 only / Kingsoft original games)
762 - 116 (0x74) => unencrypted level (byte is corrected to 131 (0x83))
763 - 131 (0x83) => unencrypted level (happens only in very rare cases)
766 if (src[1983] == 27) /* (0x1b) -- after decryption: 116 (0x74) */
768 /* this is original (encrypted) Emerald Mine I, II or III level file */
770 int first_byte = src[0];
771 unsigned char code0 = 0x65;
772 unsigned char code1 = 0x11;
774 /* decode encrypted level data */
775 for (i = 0; i < 2106; i++)
780 code0 = (code0 + 7) & 0xff;
783 src[1] = 131; /* needed for all Emerald Mine levels */
785 /* first byte is either 0xf1 (EM I and III) or 0xf5 (EM II) */
786 if (first_byte == 0xf5)
788 src[0] = 131; /* only needed for Emerald Mine II levels */
790 fix_copyright = TRUE;
793 /* ---------- this cave has V3 file format ---------- */
794 file_version = FILE_VERSION_EM_V3;
796 else if (filename_has_v1_format(filename))
798 /* ---------- this cave has V1 file format ---------- */
799 file_version = FILE_VERSION_EM_V1;
803 /* ---------- this cave has V2 file format ---------- */
804 file_version = FILE_VERSION_EM_V2;
807 /* remap elements to internal EMC level format */
808 for (i = 0; i < 2048; i++)
809 src[i] = map_v4[src[i]];
810 for (i = 2048; i < 2084; i++)
811 src[i] = map_v4_eater[src[i] >= 28 ? 0 : src[i]];
812 for (i = 2112; i < 2148; i++)
813 src[i] = src[i - 64];
815 if (fix_copyright) /* fix "(c)" sign in Emerald Mine II levels */
817 for (i = 0; i < 2048; i++)
819 src[i] = 254; /* replace 'Xdecor_1' with 'Xalpha_copyr' */
824 /* ---------- this cave has unknown file format ---------- */
826 /* if file has length of old-style level file, print (wrong) magic byte */
828 Error(ERR_WARN, "unknown magic byte 0x%02x at position 0x%04x",
831 return FILE_VERSION_EM_UNKNOWN;
834 if (file_version < FILE_VERSION_EM_V6)
837 src[2106] = 255; /* version id: */
838 src[2107] = 54; /* '6' */
839 src[2108] = 48; /* '0' */
840 src[2109] = 48; /* '0' */
844 /* stored level time of levels for the V2 player was changed to 50% of the
845 time for the V1 player (original V3 levels already considered this) */
846 if (file_version != FILE_VERSION_EM_V1 &&
847 file_version != FILE_VERSION_EM_V3)
852 for (i = 2148; i < 2172; i++)
859 /* ---------- at this stage, the cave data always has V6 format ---------- */
862 for (i = 0; i < 2048; i++)
865 for (i++; i < 2048; i++)
870 for (i = 64; i < 2048; i++)
871 if (src[i] == 63) /* replace element above 'Xacid_s' ... */
872 src[i - 64] = 101; /* ... with 'Xacid_1' */
874 /* fix acid with no base beneath it (see below for details (*)) */
875 for (i = 64; i < 2048 - 1; i++)
877 if (file_version <= FILE_VERSION_EM_V2 &&
878 src[i - 64] == 101 && src[i] != 63) /* acid without base */
880 if (src[i - 1] == 101 || /* remove acid over acid row */
882 src[i - 64] = 6; /* replace element above with 'Xblank' */
884 src[i - 64] = 255; /* replace element above with 'Xfake_acid_1' */
888 /* fix acid in eater 1 */
889 for (i = 2051; i < 2057; i++)
893 /* fix acid in eater 2 */
894 for (i = 2060; i < 2066; i++)
898 /* fix acid in eater 3 */
899 for (i = 2069; i < 2075; i++)
903 /* fix acid in eater 4 */
904 for (i = 2078; i < 2084; i++)
908 /* fix acid in eater 5 */
909 for (i = 2115; i < 2121; i++)
913 /* fix acid in eater 6 */
914 for (i = 2124; i < 2130; i++)
918 /* fix acid in eater 7 */
919 for (i = 2133; i < 2139; i++)
923 /* fix acid in eater 8 */
924 for (i = 2142; i < 2148; i++)
933 src[src[2096] << 8 | src[2097]] = 128;
937 src[src[2098] << 8 | src[2099]] = 128;
940 if ((src[2100] << 8 | src[2101]) > 9999)
946 /* time wonderwall */
947 if ((src[2102] << 8 | src[2103]) > 9999)
954 if ((src[2110] << 8 | src[2111]) > 9999)
967 if ((src[2154] << 8 | src[2155]) > 9999)
974 if ((src[2156] << 8 | src[2157]) > 9999)
982 src[2159] = map_v6[src[2159]];
985 if ((src[2160] << 8 | src[2161]) > 9999)
996 /* android move pause */
997 if ((src[2164] << 8 | src[2165]) > 9999)
1003 /* android clone pause */
1004 if ((src[2166] << 8 | src[2167]) > 9999)
1013 /* size of v6 cave */
1017 Error(ERR_DEBUG, "EM level file version: %d", file_version);
1019 return file_version;
1026 structure of emerald mine level disk files
1027 ----------------------------------------------------------------------
1029 if(len >= 2172 && (buf[2106] == 255 && buf[2107] == 54 && buf[2108] == 48 && buf[2109] == 48)) // v6
1030 if(len >= 2110 && (buf[2106] == 255 && buf[2107] == 53 && buf[2108] == 48 && buf[2109] == 48)) // v5
1031 if(len >= 2106 && (buf[1983] == 116 || buf[2047] == 116)) // v4
1032 if(len >= 2106 && (buf[1983] == 27 || buf[2047] == 219)) // v3
1034 buf[0]=241;buf[1]=248;for(i=0,j=101;i<2106;i++,j+=7)buf[i]=(buf[i]^j)-17; // decrypt
1036 number of movements (calls to logic) = time * 50 / 8
1038 {} reserved (but some broken levels use them)
1040 ----------------------------------------------------------------------
1056 2091: dynamite value
1060 2095: emeralds needed
1064 2102: wonderwall time
1066 2106: ID (0xff363030)
1072 2148: flags bit#7=NOI #6=RIS
1073 2149: wind direction bit#0=right #1=down #2=left #3=up
1074 2150: cave number bit#7=teamwork
1083 2162: ball info bit#15=switch state #8=random
1084 ; bit#0=N #1=S #2=W #3=E #4=SE #5=SW #6=NE #7=NW
1085 2164: android move speed
1086 2166: android clone speed
1088 ; bit#0=emerald #1=diamond #2=stone #3=bomb #4=nut #5=tank #6=eater
1089 ; #7=bug #8=alien #9=spring #10=balloon #11=ameuba #12=dynamite
1094 1: stone {stone_fall}
1096 3: diamond {diamond_fall}
1098 5: alien {alien_pause}
1110 17: bomb {bomb_fall}
1112 19: emerald {emerald_fall}
1122 29: drip {drip_fall}
1123 30: blank {drip_stretchB}
1124 31: drip {drip_stretch}
1125 32: stone {stone_pause}
1126 33: bomb {bomb_pause}
1127 34: diamond {diamond_pause}
1128 35: emerald {emerald_pause}
1129 36: wonderwall {wonderwallB}
1139 46: blank {sand_stonein_2}
1140 47: blank {sand_stonein_3}
1141 48: blank {sand_stonein_4}
1142 49: sand {sand_stonesand_2}
1143 50: sand {sand_stonesand_3}
1144 51: sand {sand_stonesand_4}
1145 52: sand_stone {sand_sandstone_2}
1146 53: sand_stone {sand_sandstone_3}
1147 54: sand_stone {sand_sandstone_4}
1148 55: sand {sand_stonesand_4}
1149 56: stone {sand_stoneout_2}
1163 70: spring {spring_fall}
1164 71: spring {spring_w}
1165 72: spring {spring_e}
1170 77: android {android_n_1}
1171 78: android {android_n_2}
1172 79: android {android_s_1}
1173 80: android {android_s_2}
1174 81: android {android_e_1}
1175 82: android {android_e_2}
1176 83: android {android_w_1}
1177 84: android {android_w_2}
1192 99: spring {push_spring_w}
1193 100: spring {push_spring_e}
1202 109: pause {grass_wB}
1203 110: pause {grass_eB}
1204 111: pause {grass_nB}
1205 112: pause {grass_sB}
1206 113: pause {dynamite_blank}
1207 114: nut {push_nut_w}
1208 115: nut {push_nut_e}
1209 116: steel_2 {end of level}
1211 118: pause {emerald_blank}
1212 119: bomb {push_bomb_w}
1213 120: bomb {push_bomb_e}
1214 121: stone {push_stone_w}
1215 122: stone {push_stone_e}
1216 123: pause {diamond_blank}
1217 124: pause {dirt_wB}
1218 125: pause {dirt_eB}
1219 126: pause {dirt_nB}
1220 127: pause {dirt_sB}
1257 163: fake_blank {fake_blankB}
1258 164: fake_grass {fake_grassB}
1260 166: switch {switchB}
1351 ----------------------------------------------------------------------
1367 2091: dynamite value
1371 2095: emeralds needed
1375 2102: wonderwall time
1377 2106: ID (0xff353030)
1381 1: stone {stone_fall}
1383 3: diamond {diamond_fall}
1385 5: alien {alien_pause}
1397 17: bomb {bomb_fall}
1399 19: emerald {emerald_fall}
1409 29: drip {drip_fall}
1410 30: blank {drip_stretchB}
1411 31: drip {drip_stretch}
1412 32: stone {stone_pause}
1413 33: bomb {bomb_pause}
1414 34: diamond {diamond_pause}
1415 35: emerald {emerald_pause}
1416 36: wonderwall {wonderwallB}
1426 46: blank {sand_stonein_2}
1427 47: blank {sand_stonein_3}
1428 48: blank {sand_stonein_4}
1429 49: sand {sand_stonesand_2}
1430 50: sand {sand_stonesand_3}
1431 51: sand {sand_stonesand_4}
1432 52: sand_stone {sand_sandstone_2}
1433 53: sand_stone {sand_sandstone_3}
1434 54: sand_stone {sand_sandstone_4}
1435 55: sand {sand_stonesand_4}
1436 56: stone {sand_stoneout_2}
1489 109: pause {grass_wB}
1490 110: pause {grass_eB}
1491 111: pause {grass_nB}
1492 112: pause {grass_sB}
1493 113: pause {dynamite_blank}
1494 114: nut {push_nut_w}
1495 115: nut {push_nut_e}
1496 116: steel_2 {end of level}
1497 117: dynamite_4 {boom_2}
1498 118: pause {emerald_blank}
1499 119: bomb {push_bomb_w}
1500 120: bomb {push_bomb_e}
1501 121: stone {push_stone_w}
1502 122: stone {push_stone_e}
1503 123: pause {diamond_blank}
1504 124: pause {dirt_wB}
1505 125: pause {dirt_eB}
1506 126: pause {dirt_nB}
1507 127: pause {dirt_sB}
1638 ----------------------------------------------------------------------
1654 2091: dynamite value
1658 2095: emeralds needed
1662 2102: wonderwall time
1692 26: diamond {diamond_shine}
1693 27: emerald {emerald_shine}
1696 1: stone {stone_fall}
1698 3: diamond {diamond_fall}
1700 5: alien {alien_pause}
1712 17: bomb {bomb_fall}
1714 19: emerald {emerald_fall}
1724 29: drip {drip_fall}
1725 30: blank {drip_stretchB}
1726 31: drip {drip_stretch}
1727 32: stone {stone_pause}
1728 33: bomb {bomb_pause}
1729 34: diamond {diamond_pause}
1730 35: emerald {emerald_pause}
1731 36: wonderwall {wonderwallB}
1741 46: blank {sand_stonein_2}
1742 47: blank {sand_stonein_3}
1743 48: blank {sand_stonein_4}
1744 49: sand {sand_stonesand_2}
1745 50: sand {sand_stonesand_3}
1746 51: sand {sand_stonesand_4}
1747 52: sand_stone {sand_sandstone_2}
1748 53: sand_stone {sand_sandstone_3}
1749 54: sand_stone {sand_sandstone_4}
1750 55: sand {sand_stonesand_4}
1751 56: stone {sand_stoneout_2}
1808 113: pause {dynamite_blank}
1809 114: nut {push_nut_w}
1810 115: nut {push_nut_e}
1811 116: steel_1 {end of level}
1812 117: dynamite_4 {boom_2}
1813 118: pause {emerald_blank}
1814 119: bomb {push_bomb_w}
1815 120: bomb {push_bomb_e}
1816 121: stone {push_stone_w}
1817 122: stone {push_stone_e}
1818 123: pause {diamond_blank}
1819 124: pause {dirt_wB}
1820 125: pause {dirt_eB}
1821 126: pause {dirt_nB}
1822 127: pause {dirt_sB}
1855 159: fake_grass {dirt}
1856 160: fake_grass {dirt}
1857 161: fake_grass {dirt}
1858 162: fake_grass {dirt}
1859 163: fake_grass {dirt}
1860 164: fake_grass {dirt}
1861 165: fake_grass {dirt}
1862 166: fake_grass {dirt}
1863 167: fake_grass {dirt}
1864 168: fake_grass {dirt}
1865 169: fake_grass {dirt}
1866 170: fake_grass {dirt}
1867 171: fake_grass {dirt}
1868 172: fake_grass {dirt}
1869 173: fake_grass {dirt}
1870 174: fake_grass {dirt}
1936 240: alpha_arrow_e {}
1937 241: decor_1 {alpha_copyr}
1953 ----------------------------------------------------------------------