2 * Copyright (c) 2007, 2008, 2009, Czirkos Zoltan <cirix@fw.hu>
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 // make all caves selectable.
21 static boolean gd_import_as_all_caves_selectable = TRUE;
23 // conversion table for imported bd1 caves.
24 static const GdElement bd1_import_table[] =
26 /* 0 */ O_SPACE, O_DIRT, O_BRICK, O_MAGIC_WALL,
27 /* 4 */ O_PRE_OUTBOX, O_OUTBOX, O_STEEL_EXPLODABLE, O_STEEL,
28 /* 8 */ O_FIREFLY_1, O_FIREFLY_2, O_FIREFLY_3, O_FIREFLY_4,
29 /* c */ O_FIREFLY_1, O_FIREFLY_2, O_FIREFLY_3, O_FIREFLY_4,
30 /* 10 */ O_STONE, O_STONE, O_STONE_F, O_STONE_F,
31 /* 14 */ O_DIAMOND, O_DIAMOND, O_DIAMOND_F, O_DIAMOND_F,
32 // ----- ACID: marek roth extension in crazy dream 3
33 /* 18 */ O_ACID, O_ACID, O_EXPLODE_1, O_EXPLODE_2,
34 /* 1c */ O_EXPLODE_3, O_EXPLODE_4, O_EXPLODE_5, O_PRE_DIA_1,
35 /* 20 */ O_PRE_DIA_2, O_PRE_DIA_3, O_PRE_DIA_4, O_PRE_DIA_5,
36 /* 24 */ O_PRE_DIA_5, O_INBOX, O_PRE_PL_1, O_PRE_PL_2,
37 /* 28 */ O_PRE_PL_3, O_PRE_PL_3, O_H_EXPANDING_WALL, O_H_EXPANDING_WALL,
38 /* 2c */ O_UNKNOWN, O_UNKNOWN, O_UNKNOWN, O_UNKNOWN,
39 /* 30 */ O_BUTTER_4, O_BUTTER_1, O_BUTTER_2, O_BUTTER_3,
40 /* 34 */ O_BUTTER_4, O_BUTTER_1, O_BUTTER_2, O_BUTTER_3,
41 /* 38 */ O_PLAYER, O_PLAYER, O_AMOEBA, O_AMOEBA,
42 /* 3c */ O_VOODOO, O_INVIS_OUTBOX, O_SLIME, O_UNKNOWN
45 // conversion table for imported plck caves.
46 static const GdElement plck_import_nybble[] =
48 /* 0 */ O_STONE, O_DIAMOND, O_MAGIC_WALL, O_BRICK,
49 /* 4 */ O_STEEL, O_H_EXPANDING_WALL, O_VOODOO, O_DIRT,
50 /* 8 */ O_FIREFLY_1, O_BUTTER_4, O_AMOEBA, O_SLIME,
51 /* 12 */ O_PRE_INVIS_OUTBOX, O_PRE_OUTBOX, O_INBOX, O_SPACE
54 // conversion table for imported 1stb caves.
55 static const GdElement firstboulder_import_table[] =
57 /* 0 */ O_SPACE, O_DIRT, O_BRICK, O_MAGIC_WALL,
58 /* 4 */ O_PRE_OUTBOX, O_OUTBOX, O_PRE_INVIS_OUTBOX, O_INVIS_OUTBOX,
59 /* 8 */ O_FIREFLY_1, O_FIREFLY_2, O_FIREFLY_3, O_FIREFLY_4,
60 /* c */ O_FIREFLY_1, O_FIREFLY_2, O_FIREFLY_3, O_FIREFLY_4,
61 /* 10 */ O_STONE, O_STONE, O_STONE_F, O_STONE_F,
62 /* 14 */ O_DIAMOND, O_DIAMOND, O_DIAMOND_F, O_DIAMOND_F,
63 /* 18 */ O_PRE_CLOCK_1, O_PRE_CLOCK_2, O_PRE_CLOCK_3, O_PRE_CLOCK_4,
64 /* 1c */ O_BITER_SWITCH, O_BITER_SWITCH, O_BLADDER_SPENDER, O_PRE_DIA_1,
65 /* 20 */ O_PRE_DIA_1, O_PRE_DIA_2, O_PRE_DIA_3, O_PRE_DIA_4,
66 /* 24 */ O_PRE_DIA_5, O_INBOX, O_PRE_PL_1, O_PRE_PL_2,
67 // ----- CLOCK: not mentioned in marek's bd inside faq
68 /* 28 */ O_PRE_PL_3, O_CLOCK, O_H_EXPANDING_WALL, O_H_EXPANDING_WALL,
69 /* 2c */ O_CREATURE_SWITCH, O_CREATURE_SWITCH, O_EXPANDING_WALL_SWITCH, O_EXPANDING_WALL_SWITCH,
70 /* 30 */ O_BUTTER_3, O_BUTTER_4, O_BUTTER_1, O_BUTTER_2,
71 /* 34 */ O_BUTTER_3, O_BUTTER_4, O_BUTTER_1, O_BUTTER_2,
72 /* 38 */ O_STEEL, O_SLIME, O_BOMB, O_SWEET,
73 /* 3c */ O_PRE_STONE_1, O_PRE_STONE_2, O_PRE_STONE_3, O_PRE_STONE_4,
74 /* 40 */ O_BLADDER, O_BLADDER_1, O_BLADDER_2, O_BLADDER_3,
75 /* 44 */ O_BLADDER_4, O_BLADDER_5, O_BLADDER_6, O_BLADDER_7,
76 /* 48 */ O_BLADDER_8, O_BLADDER_8, O_EXPLODE_1, O_EXPLODE_1,
77 /* 4c */ O_EXPLODE_2, O_EXPLODE_3, O_EXPLODE_4, O_EXPLODE_5,
78 /* 50 */ O_PLAYER, O_PLAYER, O_PLAYER_BOMB, O_PLAYER_BOMB,
79 /* 54 */ O_PLAYER_GLUED, O_PLAYER_GLUED, O_VOODOO, O_AMOEBA,
80 /* 58 */ O_AMOEBA, O_BOMB_TICK_1, O_BOMB_TICK_2, O_BOMB_TICK_3,
81 /* 5c */ O_BOMB_TICK_4, O_BOMB_TICK_5, O_BOMB_TICK_6, O_BOMB_TICK_7,
82 /* 60 */ O_BOMB_EXPL_1, O_BOMB_EXPL_2, O_BOMB_EXPL_3, O_BOMB_EXPL_4,
83 /* 64 */ O_GHOST, O_GHOST, O_GHOST_EXPL_1, O_GHOST_EXPL_2,
84 /* 68 */ O_GHOST_EXPL_3, O_GHOST_EXPL_4, O_GRAVESTONE, O_STONE_GLUED,
85 /* 6c */ O_DIAMOND_GLUED, O_DIAMOND_KEY, O_TRAPPED_DIAMOND, O_GRAVESTONE,
86 /* 70 */ O_WAITING_STONE, O_WAITING_STONE, O_CHASING_STONE, O_CHASING_STONE,
87 /* 74 */ O_PRE_STEEL_1, O_PRE_STEEL_2, O_PRE_STEEL_3, O_PRE_STEEL_4,
88 /* 78 */ O_BITER_1, O_BITER_2, O_BITER_3, O_BITER_4,
89 /* 7c */ O_BITER_1, O_BITER_2, O_BITER_3, O_BITER_4,
92 // conversion table for imported crazy dream caves.
93 static const GdElement crazydream_import_table[] =
95 /* 0 */ O_SPACE, O_DIRT, O_BRICK, O_MAGIC_WALL,
96 /* 4 */ O_PRE_OUTBOX, O_OUTBOX, O_PRE_INVIS_OUTBOX, O_INVIS_OUTBOX,
97 /* 8 */ O_FIREFLY_1, O_FIREFLY_2, O_FIREFLY_3, O_FIREFLY_4,
98 /* c */ O_FIREFLY_1, O_FIREFLY_2, O_FIREFLY_3, O_FIREFLY_4,
99 /* 10 */ O_STONE, O_STONE, O_STONE_F, O_STONE_F,
100 /* 14 */ O_DIAMOND, O_DIAMOND, O_DIAMOND_F, O_DIAMOND_F,
101 /* 18 */ O_PRE_CLOCK_1, O_PRE_CLOCK_2, O_PRE_CLOCK_3, O_PRE_CLOCK_4,
102 /* 1c */ O_BITER_SWITCH, O_BITER_SWITCH, O_BLADDER_SPENDER, O_PRE_DIA_1,
103 // ----- 6 different stages
104 /* 20 */ O_PRE_DIA_1, O_PRE_DIA_2, O_PRE_DIA_3, O_PRE_DIA_4,
105 /* 24 */ O_PRE_DIA_5, O_INBOX, O_PRE_PL_1, O_PRE_PL_2,
106 // ----- CLOCK: not mentioned in marek's bd inside faq
107 /* 28 */ O_PRE_PL_3, O_CLOCK, O_H_EXPANDING_WALL, O_H_EXPANDING_WALL,
108 /* 2c */ O_CREATURE_SWITCH, O_CREATURE_SWITCH, O_EXPANDING_WALL_SWITCH, O_EXPANDING_WALL_SWITCH,
109 /* 30 */ O_BUTTER_3, O_BUTTER_4, O_BUTTER_1, O_BUTTER_2,
110 /* 34 */ O_BUTTER_3, O_BUTTER_4, O_BUTTER_1, O_BUTTER_2,
111 /* 38 */ O_STEEL, O_SLIME, O_BOMB, O_SWEET,
112 /* 3c */ O_PRE_STONE_1, O_PRE_STONE_2, O_PRE_STONE_3, O_PRE_STONE_4,
113 /* 40 */ O_BLADDER, O_BLADDER_1, O_BLADDER_2, O_BLADDER_3,
114 /* 44 */ O_BLADDER_4, O_BLADDER_5, O_BLADDER_6, O_BLADDER_7,
115 /* 48 */ O_BLADDER_8, O_BLADDER_8|SCANNED, O_EXPLODE_1, O_EXPLODE_1,
116 /* 4c */ O_EXPLODE_2, O_EXPLODE_3, O_EXPLODE_4, O_EXPLODE_5,
117 /* 50 */ O_PLAYER, O_PLAYER, O_PLAYER_BOMB, O_PLAYER_BOMB,
118 /* 54 */ O_PLAYER_GLUED, O_PLAYER_GLUED, O_VOODOO, O_AMOEBA,
119 /* 58 */ O_AMOEBA, O_BOMB_TICK_1, O_BOMB_TICK_2, O_BOMB_TICK_3,
120 /* 5c */ O_BOMB_TICK_4, O_BOMB_TICK_5, O_BOMB_TICK_6, O_BOMB_TICK_7,
121 /* 60 */ O_BOMB_EXPL_1, O_BOMB_EXPL_2, O_BOMB_EXPL_3, O_BOMB_EXPL_4,
122 /* 64 */ O_GHOST, O_GHOST, O_GHOST_EXPL_1, O_GHOST_EXPL_2,
123 /* 68 */ O_GHOST_EXPL_3, O_GHOST_EXPL_4, O_GRAVESTONE, O_STONE_GLUED,
124 /* 6c */ O_DIAMOND_GLUED, O_DIAMOND_KEY, O_TRAPPED_DIAMOND, O_GRAVESTONE,
125 /* 70 */ O_WAITING_STONE, O_WAITING_STONE, O_CHASING_STONE, O_CHASING_STONE,
126 /* 74 */ O_PRE_STEEL_1, O_PRE_STEEL_2, O_PRE_STEEL_3, O_PRE_STEEL_4,
127 /* 78 */ O_BITER_1, O_BITER_2, O_BITER_3, O_BITER_4,
128 /* 7c */ O_BITER_1, O_BITER_2, O_BITER_3, O_BITER_4,
130 /* 80 */ O_POT, O_PLAYER_STIRRING, O_GRAVITY_SWITCH, O_GRAVITY_SWITCH,
131 /* 84 */ O_PNEUMATIC_HAMMER, O_PNEUMATIC_HAMMER, O_BOX, O_BOX,
132 /* 88 */ O_UNKNOWN, O_UNKNOWN, O_ACID, O_ACID,
133 /* 8c */ O_KEY_1, O_KEY_2, O_KEY_3, O_UNKNOWN,
134 /* 90 */ O_UNKNOWN, O_UNKNOWN, O_UNKNOWN, O_UNKNOWN,
135 /* 94 */ O_UNKNOWN, O_TELEPORTER, O_UNKNOWN, O_SKELETON,
136 /* 98 */ O_WATER, O_WATER_16, O_WATER_15, O_WATER_14,
137 /* 9c */ O_WATER_13, O_WATER_12, O_WATER_11, O_WATER_10,
138 /* a0 */ O_WATER_9, O_WATER_8, O_WATER_7, O_WATER_6,
139 /* a4 */ O_WATER_5, O_WATER_4, O_WATER_3, O_WATER_2,
140 /* a8 */ O_WATER_1, O_COW_ENCLOSED_1, O_COW_ENCLOSED_2, O_COW_ENCLOSED_3,
141 /* ac */ O_COW_ENCLOSED_4, O_COW_ENCLOSED_5, O_COW_ENCLOSED_6, O_COW_ENCLOSED_7,
142 /* b0 */ O_COW_1, O_COW_2, O_COW_3, O_COW_4,
143 /* b4 */ O_COW_1, O_COW_2, O_COW_3, O_COW_4,
144 /* b8 */ O_DIRT_GLUED, O_STEEL_EXPLODABLE, O_DOOR_1, O_DOOR_2,
145 /* bc */ O_DOOR_3, O_FALLING_WALL, O_FALLING_WALL_F, O_FALLING_WALL_F,
146 /* c0 */ O_WALLED_DIAMOND, O_UNKNOWN, O_WALLED_KEY_1, O_WALLED_KEY_2,
147 /* c5 = brick?! (vital key), c7 = dirt?! (think twice) */
148 /* c7 = dirt, as it has a code which will change it to dirt. */
149 /* c4 */ O_WALLED_KEY_3, O_BRICK, O_UNKNOWN, O_DIRT,
150 /* c8 */ O_DIRT2, O_UNKNOWN, O_UNKNOWN, O_UNKNOWN,
151 /* cc */ O_UNKNOWN, O_UNKNOWN, O_UNKNOWN, O_UNKNOWN,
152 /* d0 */ O_UNKNOWN, O_UNKNOWN, O_UNKNOWN, O_UNKNOWN,
153 /* d4 */ O_UNKNOWN, O_UNKNOWN, O_UNKNOWN, O_UNKNOWN,
154 /* d8 */ O_UNKNOWN, O_UNKNOWN, O_UNKNOWN, O_UNKNOWN,
155 /* dc */ O_UNKNOWN, O_UNKNOWN, O_UNKNOWN, O_UNKNOWN,
156 /* e0 */ O_ALT_FIREFLY_1, O_ALT_FIREFLY_2, O_ALT_FIREFLY_3, O_ALT_FIREFLY_4,
157 /* e4 */ O_ALT_FIREFLY_1, O_ALT_FIREFLY_2, O_ALT_FIREFLY_3, O_ALT_FIREFLY_4,
158 /* e8 */ O_ALT_BUTTER_3, O_ALT_BUTTER_4, O_ALT_BUTTER_1, O_ALT_BUTTER_2,
159 /* ec */ O_ALT_BUTTER_3, O_ALT_BUTTER_4, O_ALT_BUTTER_1, O_ALT_BUTTER_2,
160 /* f0 */ O_WATER, O_WATER, O_WATER, O_WATER,
161 /* f4 */ O_WATER, O_WATER, O_WATER, O_WATER,
162 /* f8 */ O_WATER, O_WATER, O_WATER, O_WATER,
163 /* fc */ O_WATER, O_WATER, O_WATER, O_WATER,
166 // conversion table for imported 1stb caves.
167 const GdElement gd_crazylight_import_table[] =
169 /* 0 */ O_SPACE, O_DIRT, O_BRICK, O_MAGIC_WALL,
170 /* 4 */ O_PRE_OUTBOX, O_OUTBOX, O_PRE_INVIS_OUTBOX, O_INVIS_OUTBOX,
171 /* 8 */ O_FIREFLY_1, O_FIREFLY_2, O_FIREFLY_3, O_FIREFLY_4,
172 /* c */ O_FIREFLY_1|SCANNED, O_FIREFLY_2|SCANNED, O_FIREFLY_3|SCANNED, O_FIREFLY_4|SCANNED,
173 /* 10 */ O_STONE, O_STONE|SCANNED, O_STONE_F, O_STONE_F|SCANNED,
174 /* 14 */ O_DIAMOND, O_DIAMOND|SCANNED, O_DIAMOND_F, O_DIAMOND_F|SCANNED,
175 /* 18 */ O_PRE_CLOCK_1, O_PRE_CLOCK_2, O_PRE_CLOCK_3, O_PRE_CLOCK_4,
176 /* 1c */ O_BITER_SWITCH, O_BITER_SWITCH, O_BLADDER_SPENDER, O_PRE_DIA_1,
177 // ----- 6 different stages, the first is the pre_dia_0
178 /* 20 */ O_PRE_DIA_1, O_PRE_DIA_2, O_PRE_DIA_3, O_PRE_DIA_4,
179 /* 24 */ O_PRE_DIA_5, O_INBOX, O_PRE_PL_1, O_PRE_PL_2,
180 // ----- CLOCK: not mentioned in marek's bd inside faq
181 /* 28 */ O_PRE_PL_3, O_CLOCK, O_H_EXPANDING_WALL, O_H_EXPANDING_WALL|SCANNED,
182 /* 2c */ O_CREATURE_SWITCH, O_CREATURE_SWITCH, O_EXPANDING_WALL_SWITCH, O_EXPANDING_WALL_SWITCH,
183 /* 30 */ O_BUTTER_3, O_BUTTER_4, O_BUTTER_1, O_BUTTER_2,
184 /* 34 */ O_BUTTER_3|SCANNED, O_BUTTER_4|SCANNED, O_BUTTER_1|SCANNED, O_BUTTER_2|SCANNED,
185 /* 38 */ O_STEEL, O_SLIME, O_BOMB, O_SWEET,
186 /* 3c */ O_PRE_STONE_1, O_PRE_STONE_2, O_PRE_STONE_3, O_PRE_STONE_4,
187 /* 40 */ O_BLADDER, O_BLADDER_1, O_BLADDER_2, O_BLADDER_3,
188 /* 44 */ O_BLADDER_4, O_BLADDER_5, O_BLADDER_6, O_BLADDER_7,
189 /* 48 */ O_BLADDER_8, O_BLADDER_8|SCANNED, O_EXPLODE_1, O_EXPLODE_1,
190 /* 4c */ O_EXPLODE_2, O_EXPLODE_3, O_EXPLODE_4, O_EXPLODE_5,
191 /* 50 */ O_PLAYER, O_PLAYER|SCANNED, O_PLAYER_BOMB, O_PLAYER_BOMB|SCANNED,
192 /* 54 */ O_PLAYER_GLUED, O_PLAYER_GLUED|SCANNED, O_VOODOO, O_AMOEBA,
193 /* 58 */ O_AMOEBA|SCANNED, O_BOMB_TICK_1, O_BOMB_TICK_2, O_BOMB_TICK_3,
194 /* 5c */ O_BOMB_TICK_4, O_BOMB_TICK_5, O_BOMB_TICK_6, O_BOMB_TICK_7,
195 /* 60 */ O_BOMB_EXPL_1, O_BOMB_EXPL_2, O_BOMB_EXPL_3, O_BOMB_EXPL_4,
196 /* 64 */ O_ACID, O_ACID, O_FALLING_WALL, O_FALLING_WALL_F,
197 /* 68 */ O_FALLING_WALL_F|SCANNED, O_BOX, O_GRAVESTONE, O_STONE_GLUED,
198 /* 6c */ O_DIAMOND_GLUED, O_DIAMOND_KEY, O_TRAPPED_DIAMOND, O_GRAVESTONE,
199 /* 70 */ O_WAITING_STONE, O_WAITING_STONE|SCANNED, O_CHASING_STONE, O_CHASING_STONE|SCANNED,
200 /* 74 */ O_PRE_STEEL_1, O_PRE_STEEL_2, O_PRE_STEEL_3, O_PRE_STEEL_4,
201 /* 78 */ O_BITER_1, O_BITER_2, O_BITER_3, O_BITER_4,
202 /* 7c */ O_BITER_1|SCANNED, O_BITER_2|SCANNED, O_BITER_3|SCANNED, O_BITER_4|SCANNED,
205 GdPropertyDefault gd_defaults_bd1[] =
207 { CAVE_OFFSET(level_amoeba_threshold), 200 },
208 { CAVE_OFFSET(amoeba_growth_prob), 31250 },
209 { CAVE_OFFSET(amoeba_fast_growth_prob), 250000 },
210 { CAVE_OFFSET(amoeba_timer_started_immediately), TRUE },
211 { CAVE_OFFSET(amoeba_timer_wait_for_hatching), FALSE },
212 { CAVE_OFFSET(lineshift), TRUE },
213 { CAVE_OFFSET(wraparound_objects), TRUE },
214 { CAVE_OFFSET(diagonal_movements), FALSE },
215 { CAVE_OFFSET(voodoo_collects_diamonds), FALSE },
216 { CAVE_OFFSET(voodoo_dies_by_stone), FALSE },
217 { CAVE_OFFSET(voodoo_disappear_in_explosion), TRUE },
218 { CAVE_OFFSET(voodoo_any_hurt_kills_player), FALSE },
219 { CAVE_OFFSET(creatures_backwards), FALSE },
220 { CAVE_OFFSET(creatures_direction_auto_change_on_start), FALSE },
221 { CAVE_OFFSET(creatures_direction_auto_change_time), 0 },
222 { CAVE_OFFSET(level_hatching_delay_time[0]), 2 },
223 { CAVE_OFFSET(intermission_instantlife), TRUE },
224 { CAVE_OFFSET(intermission_rewardlife), FALSE },
225 { CAVE_OFFSET(magic_wall_stops_amoeba), TRUE },
226 { CAVE_OFFSET(magic_wall_breakscan), TRUE },
227 { CAVE_OFFSET(magic_timer_zero_is_infinite), TRUE },
228 { CAVE_OFFSET(magic_timer_wait_for_hatching), FALSE },
229 { CAVE_OFFSET(pushing_stone_prob), 250000 },
230 { CAVE_OFFSET(pushing_stone_prob_sweet), 1000000 },
231 { CAVE_OFFSET(active_is_first_found), FALSE },
232 { CAVE_OFFSET(short_explosions), TRUE },
233 { CAVE_OFFSET(slime_predictable), TRUE },
234 { CAVE_OFFSET(snap_element), O_SPACE },
235 { CAVE_OFFSET(max_time), 999 },
237 { CAVE_OFFSET(scheduling), GD_SCHEDULING_BD1 },
238 { CAVE_OFFSET(pal_timing), TRUE },
243 GdPropertyDefault gd_defaults_bd2[] =
245 { CAVE_OFFSET(level_amoeba_threshold), 200 },
246 { CAVE_OFFSET(amoeba_growth_prob), 31250 },
247 { CAVE_OFFSET(amoeba_fast_growth_prob), 250000 },
248 { CAVE_OFFSET(amoeba_timer_started_immediately), FALSE },
249 { CAVE_OFFSET(amoeba_timer_wait_for_hatching), FALSE },
250 { CAVE_OFFSET(lineshift), TRUE },
251 { CAVE_OFFSET(wraparound_objects), TRUE },
252 { CAVE_OFFSET(diagonal_movements), FALSE },
253 { CAVE_OFFSET(voodoo_collects_diamonds), FALSE },
254 { CAVE_OFFSET(voodoo_dies_by_stone), FALSE },
255 { CAVE_OFFSET(voodoo_disappear_in_explosion), TRUE },
256 { CAVE_OFFSET(voodoo_any_hurt_kills_player), FALSE },
257 { CAVE_OFFSET(creatures_backwards), FALSE },
258 { CAVE_OFFSET(creatures_direction_auto_change_on_start), FALSE },
259 { CAVE_OFFSET(creatures_direction_auto_change_time), 0 },
260 { CAVE_OFFSET(level_hatching_delay_time[0]), 2 },
261 { CAVE_OFFSET(intermission_instantlife), TRUE },
262 { CAVE_OFFSET(intermission_rewardlife), FALSE },
263 { CAVE_OFFSET(magic_wall_stops_amoeba), FALSE }, // marek roth bd inside faq 3.0
264 { CAVE_OFFSET(magic_timer_zero_is_infinite), TRUE },
265 { CAVE_OFFSET(magic_timer_wait_for_hatching), FALSE },
266 { CAVE_OFFSET(pushing_stone_prob), 250000 },
267 { CAVE_OFFSET(pushing_stone_prob_sweet), 1000000 },
268 { CAVE_OFFSET(active_is_first_found), FALSE },
269 { CAVE_OFFSET(short_explosions), TRUE },
270 { CAVE_OFFSET(slime_predictable), TRUE },
271 { CAVE_OFFSET(snap_element), O_SPACE },
272 { CAVE_OFFSET(max_time), 999 },
274 { CAVE_OFFSET(pal_timing), TRUE },
275 { CAVE_OFFSET(scheduling), GD_SCHEDULING_BD2 },
280 GdPropertyDefault gd_defaults_plck[] =
282 { CAVE_OFFSET(amoeba_growth_prob), 31250 },
283 { CAVE_OFFSET(amoeba_fast_growth_prob), 250000 },
284 { CAVE_OFFSET(amoeba_timer_started_immediately), FALSE },
285 { CAVE_OFFSET(amoeba_timer_wait_for_hatching), FALSE },
286 { CAVE_OFFSET(lineshift), TRUE },
287 { CAVE_OFFSET(wraparound_objects), TRUE },
288 { CAVE_OFFSET(border_scan_first_and_last), FALSE },
289 { CAVE_OFFSET(diagonal_movements), FALSE },
290 { CAVE_OFFSET(voodoo_collects_diamonds), FALSE },
291 { CAVE_OFFSET(voodoo_dies_by_stone), FALSE },
292 { CAVE_OFFSET(voodoo_disappear_in_explosion), TRUE },
293 { CAVE_OFFSET(voodoo_any_hurt_kills_player), FALSE },
294 { CAVE_OFFSET(creatures_backwards), FALSE },
295 { CAVE_OFFSET(creatures_direction_auto_change_on_start), FALSE },
296 { CAVE_OFFSET(creatures_direction_auto_change_time), 0 },
297 { CAVE_OFFSET(level_hatching_delay_time[0]), 2 },
298 { CAVE_OFFSET(intermission_instantlife), TRUE },
299 { CAVE_OFFSET(intermission_rewardlife), FALSE },
300 { CAVE_OFFSET(magic_wall_stops_amoeba), FALSE },
301 { CAVE_OFFSET(magic_timer_zero_is_infinite), TRUE },
302 { CAVE_OFFSET(magic_timer_wait_for_hatching), FALSE },
303 { CAVE_OFFSET(pushing_stone_prob), 250000 },
304 { CAVE_OFFSET(pushing_stone_prob_sweet), 1000000 },
305 { CAVE_OFFSET(active_is_first_found), FALSE },
306 { CAVE_OFFSET(short_explosions), TRUE },
307 { CAVE_OFFSET(snap_element), O_SPACE },
308 { CAVE_OFFSET(max_time), 999 },
310 { CAVE_OFFSET(pal_timing), TRUE },
311 { CAVE_OFFSET(scheduling), GD_SCHEDULING_PLCK },
316 GdPropertyDefault gd_defaults_1stb[] =
318 { CAVE_OFFSET(amoeba_growth_prob), 31250 },
319 { CAVE_OFFSET(amoeba_fast_growth_prob), 250000 },
320 { CAVE_OFFSET(amoeba_timer_started_immediately), FALSE },
321 { CAVE_OFFSET(amoeba_timer_wait_for_hatching), TRUE },
322 { CAVE_OFFSET(lineshift), TRUE },
323 { CAVE_OFFSET(wraparound_objects), TRUE },
324 { CAVE_OFFSET(voodoo_collects_diamonds), TRUE },
325 { CAVE_OFFSET(voodoo_dies_by_stone), TRUE },
326 { CAVE_OFFSET(voodoo_disappear_in_explosion), FALSE },
327 { CAVE_OFFSET(voodoo_any_hurt_kills_player), FALSE },
328 { CAVE_OFFSET(creatures_direction_auto_change_on_start), TRUE },
329 { CAVE_OFFSET(level_hatching_delay_time[0]), 2 },
330 { CAVE_OFFSET(intermission_instantlife), FALSE },
331 { CAVE_OFFSET(intermission_rewardlife), TRUE },
332 { CAVE_OFFSET(magic_timer_zero_is_infinite), TRUE },
333 { CAVE_OFFSET(magic_timer_wait_for_hatching), TRUE },
334 { CAVE_OFFSET(pushing_stone_prob), 250000 },
335 { CAVE_OFFSET(pushing_stone_prob_sweet), 1000000 },
336 { CAVE_OFFSET(active_is_first_found), TRUE },
337 { CAVE_OFFSET(short_explosions), FALSE },
338 { CAVE_OFFSET(slime_predictable), TRUE },
339 { CAVE_OFFSET(snap_element), O_SPACE },
340 { CAVE_OFFSET(max_time), 999 },
342 { CAVE_OFFSET(pal_timing), TRUE },
343 { CAVE_OFFSET(scheduling), GD_SCHEDULING_PLCK },
344 // not immediately to diamond, but with animation
345 { CAVE_OFFSET(amoeba_enclosed_effect), O_PRE_DIA_1 },
346 { CAVE_OFFSET(dirt_looks_like), O_DIRT2 },
351 GdPropertyDefault gd_defaults_crdr_7[] =
353 { CAVE_OFFSET(amoeba_growth_prob), 31250 },
354 { CAVE_OFFSET(amoeba_fast_growth_prob), 250000 },
355 { CAVE_OFFSET(amoeba_timer_started_immediately), FALSE },
356 { CAVE_OFFSET(amoeba_timer_wait_for_hatching), TRUE },
357 { CAVE_OFFSET(lineshift), TRUE },
358 { CAVE_OFFSET(wraparound_objects), TRUE },
359 { CAVE_OFFSET(voodoo_collects_diamonds), TRUE },
360 { CAVE_OFFSET(voodoo_dies_by_stone), TRUE },
361 { CAVE_OFFSET(voodoo_disappear_in_explosion), FALSE },
362 { CAVE_OFFSET(voodoo_any_hurt_kills_player), FALSE },
363 { CAVE_OFFSET(creatures_direction_auto_change_on_start), FALSE },
364 { CAVE_OFFSET(level_hatching_delay_time[0]), 2 },
365 { CAVE_OFFSET(intermission_instantlife), FALSE },
366 { CAVE_OFFSET(intermission_rewardlife), TRUE },
367 { CAVE_OFFSET(magic_timer_zero_is_infinite), FALSE },
368 { CAVE_OFFSET(magic_timer_wait_for_hatching), TRUE },
369 { CAVE_OFFSET(pushing_stone_prob), 250000 },
370 { CAVE_OFFSET(pushing_stone_prob_sweet), 1000000 },
371 { CAVE_OFFSET(active_is_first_found), TRUE },
372 { CAVE_OFFSET(short_explosions), FALSE },
373 { CAVE_OFFSET(slime_predictable), TRUE },
374 { CAVE_OFFSET(snap_element), O_SPACE },
375 { CAVE_OFFSET(max_time), 999 },
377 { CAVE_OFFSET(pal_timing), TRUE },
378 { CAVE_OFFSET(scheduling), GD_SCHEDULING_CRDR },
379 // not immediately to diamond, but with animation
380 { CAVE_OFFSET(amoeba_enclosed_effect), O_PRE_DIA_1 },
381 { CAVE_OFFSET(water_does_not_flow_down), TRUE },
382 // in crdr, skeletons can also be used to open the gate
383 { CAVE_OFFSET(skeletons_worth_diamonds), 1 },
384 // the intermission "survive" needs this flag
385 { CAVE_OFFSET(gravity_affects_all), FALSE },
390 GdPropertyDefault gd_defaults_crli[] =
392 { CAVE_OFFSET(amoeba_growth_prob), 31250 },
393 { CAVE_OFFSET(amoeba_fast_growth_prob), 250000 },
394 { CAVE_OFFSET(amoeba_timer_started_immediately), FALSE },
395 { CAVE_OFFSET(amoeba_timer_wait_for_hatching), TRUE },
396 { CAVE_OFFSET(lineshift), TRUE },
397 { CAVE_OFFSET(wraparound_objects), TRUE },
398 { CAVE_OFFSET(voodoo_collects_diamonds), TRUE },
399 { CAVE_OFFSET(voodoo_dies_by_stone), TRUE },
400 { CAVE_OFFSET(voodoo_disappear_in_explosion), FALSE },
401 { CAVE_OFFSET(voodoo_any_hurt_kills_player), FALSE },
402 { CAVE_OFFSET(creatures_direction_auto_change_on_start), FALSE },
403 { CAVE_OFFSET(level_hatching_delay_time[0]), 2 },
404 { CAVE_OFFSET(intermission_instantlife), FALSE },
405 { CAVE_OFFSET(intermission_rewardlife), TRUE },
406 { CAVE_OFFSET(magic_timer_zero_is_infinite), FALSE },
407 { CAVE_OFFSET(magic_timer_wait_for_hatching), TRUE },
408 { CAVE_OFFSET(pushing_stone_prob), 250000 },
409 { CAVE_OFFSET(pushing_stone_prob_sweet), 1000000 },
410 { CAVE_OFFSET(active_is_first_found), TRUE },
411 { CAVE_OFFSET(short_explosions), FALSE },
412 { CAVE_OFFSET(slime_predictable), TRUE },
413 { CAVE_OFFSET(max_time), 999 },
415 { CAVE_OFFSET(pal_timing), TRUE },
416 { CAVE_OFFSET(scheduling), GD_SCHEDULING_PLCK },
417 // not immediately to diamond, but with animation
418 { CAVE_OFFSET(amoeba_enclosed_effect), O_PRE_DIA_1 },
424 // internal character (letter) codes in c64 games.
425 // missing: "triple line" after >, diamond between ()s, player's head after )
426 // used for converting names of caves imported from crli and other types of binary data
427 const char gd_bd_internal_chars[] =
428 " ,!./0123456789:*<=> ABCDEFGHIJKLMNOPQRSTUVWXYZ( ) _";
430 // used for bdcff engine flag.
431 const char *gd_engines[] =
441 // to convert predictable slime values to bit masks
442 static int slime_shift_msb(int c64_data)
448 for (i = 0; i < c64_data; i++)
449 // shift in this many msb 1's
450 perm = (0x100|perm) >> 1;
455 static GdElement bd1_import(byte c, int i)
457 if (c < ARRAY_SIZE(bd1_import_table))
458 return bd1_import_table[c];
460 Warn("Invalid BD1 element in imported file at cave data %d: %d", i, c);
465 // deluxe caves 1 contained a special element, non-sloped brick.
466 static GdElement deluxecaves_1_import(byte c, int i)
468 GdElement e = bd1_import(c, i);
470 if (e == O_H_EXPANDING_WALL)
471 e = O_BRICK_NON_SLOPED;
476 static GdElement firstboulder_import(byte c, int i)
478 if (c < ARRAY_SIZE(firstboulder_import_table))
479 return firstboulder_import_table[c];
481 Warn("Invalid 1stB element in imported file at cave data %d: %d", i, c);
486 static GdElement crazylight_import(byte c, int i)
488 if (c < ARRAY_SIZE(gd_crazylight_import_table))
489 return gd_crazylight_import_table[c] & O_MASK; // & O_MASK: do not import "scanned" flag
491 Warn("Invalid CrLi element in imported file at cave data %d: %d", i, c);
496 GdPropertyDefault *gd_get_engine_default_array(GdEngine engine)
501 return gd_defaults_bd1;
505 return gd_defaults_bd2;
509 return gd_defaults_plck;
513 return gd_defaults_1stb;
516 case GD_ENGINE_CRDR7:
517 return gd_defaults_crdr_7;
521 return gd_defaults_crli;
524 // to avoid compiler warning
525 case GD_ENGINE_INVALID:
529 return gd_defaults_bd1;
532 void gd_cave_set_engine_defaults(GdCave *cave, GdEngine engine)
534 gd_cave_set_defaults_from_array(cave, gd_get_engine_default_array(engine));
536 // these have hardcoded ckdelay.
537 // setting this ckdelay array does not fit into the gd_struct_default scheme.
538 if (engine == GD_ENGINE_BD1)
540 cave->level_ckdelay[0] = 12;
541 cave->level_ckdelay[1] = 6;
542 cave->level_ckdelay[2] = 3;
543 cave->level_ckdelay[3] = 1;
544 cave->level_ckdelay[4] = 0;
547 if (engine == GD_ENGINE_BD2)
549 cave->level_ckdelay[0] = 9; // 180ms
550 cave->level_ckdelay[1] = 8; // 160ms
551 cave->level_ckdelay[2] = 7; // 140ms
552 cave->level_ckdelay[3] = 6; // 120ms
553 cave->level_ckdelay[4] = 6; // 120ms (!) not faster than level4
557 GdEngine gd_cave_get_engine_from_string(const char *param)
561 for (i = 0; i < GD_ENGINE_INVALID; i++)
562 if (strcasecmp(param, gd_engines[i]) == 0)
565 return GD_ENGINE_INVALID;
568 // ============================================================================
570 // cave import routines.
571 // take a cave, data, and maybe remaining bytes.
572 // return the number of bytes read, -1 if error.
574 // ============================================================================
577 take care of required diamonds values == 0 or > 100.
578 in original bd, the counter was only two-digit. so bd3 cave f
579 says 150 diamonds required, but you only had to collect 50.
580 also, gate opening is triggered by incrementing diamond
581 count and THEN checking if more required; so if required was
582 0, you had to collect 100. (also check crazy light 8 cave "1000")
584 http://www.boulder-dash.nl/forum/viewtopic.php?t=88
587 // import bd1 cave data into our format.
588 static int cave_copy_from_bd1(GdCave *cave, const byte *data, int remaining_bytes,
589 GdCavefileFormat format)
591 int length, direction;
597 GdElement (* import_func) (byte c, int i);
600 // cant be shorted than this: header + no objects + delimiter
601 if (remaining_bytes < 33)
603 Error("truncated BD1 cave data, %d bytes", remaining_bytes);
608 gd_cave_set_engine_defaults(cave, GD_ENGINE_BD1);
610 if (format == GD_FORMAT_BD1_ATARI)
611 cave->scheduling = GD_SCHEDULING_BD1_ATARI;
613 if (format == GD_FORMAT_DC1)
614 import_func = deluxecaves_1_import;
616 import_func = bd1_import;
618 // set visible size for intermission
619 if (cave->intermission)
625 // cave number data[0]
626 cave->diamond_value = data[2];
627 cave->extra_diamond_value = data[3];
629 for (level = 0; level < 5; level++)
631 cave->level_amoeba_time[level] = data[1];
633 // 0 immediately underflowed to 999, so we use 999. example: sendydash 3, cave 02.
634 if (cave->level_amoeba_time[level] == 0)
635 cave->level_amoeba_time[level] = 999;
637 cave->level_magic_wall_time[level] = data[1];
638 cave->level_rand[level] = data[4 + level];
639 cave->level_diamonds[level] = data[9 + level] % 100; // check comment above
641 // gate opening is checked AFTER adding to diamonds collected, so 0 here means 100 to collect
642 if (cave->level_diamonds[level] == 0)
643 cave->level_diamonds[level] = 100;
644 cave->level_time[level] = data[14 + level];
648 LogicDeLuxe extension: acid
649 $16 Acid speed (unused in the original BD1)
650 $17 Bit 2: if set, Acid's original position converts to explosion puff during spreading.
651 Otherwise, Acid remains intact, ie. it's just growing. (unused in the original BD1)
652 $1C Acid eats this element. (also Probability of element 1)
654 there is no problem importing these; as other bd1 caves did not contain acid at all,
655 so it does not matter how we set the values.
658 // 0x1c index: same as probability1 !!!!! don't be surprised. we do a &0x3f because of this
659 cave->acid_eats_this = import_func(data[0x1c] & 0x3F, 0x1c);
661 // acid speed, *1e6 as probabilities are stored in int
662 cave->acid_spread_ratio = data[0x16] / 255.0 * 1E6 + 0.5;
664 cave->acid_turns_to = (data[0x17] & (1 << 2)) ? O_EXPLODE_3 : O_ACID;
666 if (format == GD_FORMAT_BD1_ATARI)
669 cave->color1 = gd_atari_color(data[0x13]);
670 cave->color2 = gd_atari_color(data[0x14]);
671 cave->color3 = gd_atari_color(data[0x15]);
672 cave->color4 = gd_atari_color(data[0x16]); // in atari, amoeba was green
673 cave->color5 = gd_atari_color(data[0x16]); // in atari, slime was green
674 cave->colorb = gd_atari_color(data[0x17]); // border = background
675 cave->color0 = gd_atari_color(data[0x17]); // background
680 cave->colorb = gd_c64_color(0); // border = background, fixed color
681 cave->color0 = gd_c64_color(0); // background, fixed color
682 cave->color1 = gd_c64_color(data[0x13] & 0xf);
683 cave->color2 = gd_c64_color(data[0x14] & 0xf);
684 cave->color3 = gd_c64_color(data[0x15] & 0x7); // lower 3 bits only (vic-ii worked this way)
685 cave->color4 = cave->color3; // in bd1, amoeba was color3
686 cave->color5 = cave->color3; // no slime, but let it be color 3
690 for (i = 0; i < 4; i++)
692 cave->random_fill[i] = import_func(data[24 + i], 24 + i);
693 cave->random_fill_probability[i] = data[28 + i];
697 * Decode the explicit cave data
701 while (data[index] != 0xFF && index < remaining_bytes && index < 255)
705 // crazy dream 3 extension:
708 int x1, y1, nx, ny, dx, dy;
711 // as this one uses nonstandard dx dy values, create points instead
712 elem = import_func(data[index + 1], index + 1);
713 x1 = data[index + 2];
714 y1 = data[index + 3] - 2;
715 nx = data[index + 4];
716 ny = data[index + 5];
717 dx = data[index + 6];
718 dy = data[index + 7] + 1;
720 for (y = 0; y < ny; y++)
722 for (x = 0; x < nx; x++)
724 int pos = x1 + y1 * 40 + y * dy * 40 + x * dx;
726 cave->objects = list_append(cave->objects, gd_object_new_point(GD_OBJECT_LEVEL_ALL, pos % 40, pos / 40, elem));
734 // object is code & 3f, object type is upper 2 bits
735 elem = import_func(code & 0x3F, index);
737 switch ((code >> 6) & 3)
740 x1 = data[index + 1];
741 y1 = data[index + 2] - 2;
743 if (x1 >= cave->w || y1 >= cave->h)
744 Warn("invalid point coordinates %d,%d at byte %d", x1, y1, index);
746 cave->objects = list_append(cave->objects, gd_object_new_point(GD_OBJECT_LEVEL_ALL, x1, y1, elem));
752 x1 = data[index + 1];
753 y1 = data[index + 2] - 2;
754 length = (byte)data[index + 3] - 1;
755 direction = data[index + 4];
759 Warn("line length negative, not displaying line at all, at byte %d", index);
763 if (direction > GD_MV_UP_LEFT)
765 Warn("invalid line direction %d at byte %d", direction, index);
766 direction = GD_MV_STILL;
769 x2 = x1 + length * gd_dx[direction + 1];
770 y2 = y1 + length * gd_dy[direction + 1];
776 Warn("invalid line coordinates %d,%d %d,%d at byte %d", x1, y1, x2, y2, index);
778 cave->objects = list_append(cave->objects, gd_object_new_line(GD_OBJECT_LEVEL_ALL, x1, y1, x2, y2, elem));
784 case 2: // 10: FILLED RECTANGLE
785 x1 = data[index + 1];
786 y1 = data[index + 2] - 2;
787 x2 = x1 + data[index + 3] - 1; // width
788 y2 = y1 + data[index + 4] - 1; // height
794 Warn("invalid filled rectangle coordinates %d,%d %d,%d at byte %d", x1, y1, x2, y2, index);
796 cave->objects = list_append(cave->objects, gd_object_new_filled_rectangle(GD_OBJECT_LEVEL_ALL, x1, y1, x2, y2, elem, import_func(data[index + 5], index + 5)));
801 case 3: // 11: OPEN RECTANGLE (OUTLINE)
802 x1 = data[index + 1];
803 y1 = data[index + 2] - 2;
804 x2 = x1 + data[index + 3] - 1;
805 y2 = y1 + data[index + 4] - 1;
811 Warn("invalid rectangle coordinates %d,%d %d,%d at byte %d", x1, y1, x2, y2, index);
813 cave->objects = list_append(cave->objects, gd_object_new_rectangle(GD_OBJECT_LEVEL_ALL, x1, y1, x2, y2, elem));
821 if (data[index] != 0xFF)
823 Error("import error, cave not delimited with 0xFF");
830 // import bd2 cave data into our format. return number of bytes if pointer passed.
831 // this is pretty much the same as above, only the encoding was different.
832 static int cave_copy_from_bd2(GdCave *cave, const byte *data, int remaining_bytes,
833 GdCavefileFormat format)
838 int x1, y1, x2, y2, dx, dy;
841 if (remaining_bytes < 0x1A + 5)
843 Error("truncated BD2 cave data, %d bytes", remaining_bytes);
847 gd_cave_set_engine_defaults(cave, GD_ENGINE_BD2);
849 if (format == GD_FORMAT_BD2_ATARI)
850 cave->scheduling = GD_SCHEDULING_BD2_PLCK_ATARI;
852 // set visible size for intermission
853 if (cave->intermission)
859 cave->diamond_value = data[1];
860 cave->extra_diamond_value = data[2];
862 for (i = 0; i < 5; i++)
864 // 0 immediately underflowed to 999, so we use 999. example: sendydash 3, cave 02.
865 cave->level_amoeba_time[i] = data[0] == 0 ? 999 : data[0];
866 cave->level_rand[i] = data[13 + i];
868 // gate opening is checked AFTER adding to diamonds collected, so 0 here is 1000 needed
869 cave->level_diamonds[i] = data[8 + i] == 0 ? 1000 : data[8 + i];
870 cave->level_time[i] = data[3 + i];
871 cave->level_magic_wall_time[i] = data[0];
874 for (i = 0; i < 4; i++)
876 cave->random_fill[i] = bd1_import(data[0x16 + i], 0x16 + i);
877 cave->random_fill_probability[i] = data[0x12 + i];
881 * Decode the explicit cave data
885 while (data[index] != 0xFF && index < remaining_bytes)
890 int length, direction;
895 elem = bd1_import(data[index + 1], index + 1);
896 y1 = data[index + 2];
897 x1 = data[index + 3];
899 // they are multiplied by two - 0 is up, 2 is upright, 4 is right...
900 direction = data[index + 4] / 2;
901 length = data[index + 5] - 1;
903 if (direction > GD_MV_UP_LEFT)
905 Warn("invalid line direction %d at byte %d", direction, index);
906 direction = GD_MV_STILL;
909 x2 = x1 + length * gd_dx[direction + 1];
910 y2 = y1 + length * gd_dy[direction + 1];
916 Warn("invalid line coordinates %d,%d %d,%d at byte %d", x1, y1, x2, y2, index);
918 cave->objects = list_append(cave->objects, gd_object_new_line(GD_OBJECT_LEVEL_ALL, x1, y1, x2, y2, elem));
923 case 1: // OPEN RECTANGLE
924 elem = bd1_import(data[index + 1], index + 1);
925 y1 = data[index + 2];
926 x1 = data[index + 3];
927 y2 = y1 + data[index + 4] - 1; // height
928 x2 = x1 + data[index + 5] - 1;
934 Warn("invalid rectangle coordinates %d,%d %d,%d at byte %d", x1, y1, x2, y2, index);
936 cave->objects = list_append(cave->objects, gd_object_new_rectangle(GD_OBJECT_LEVEL_ALL, x1, y1, x2, y2, elem));
941 case 2: // FILLED RECTANGLE
942 elem = bd1_import(data[index + 1], index + 1);
943 y1 = data[index + 2];
944 x1 = data[index + 3];
945 y2 = y1 + data[index + 4] - 1;
946 x2 = x1 + data[index + 5] - 1;
952 Warn("invalid filled rectangle coordinates %d,%d %d,%d at byte %d", x1, y1, x2, y2, index);
954 cave->objects = list_append(cave->objects, gd_object_new_filled_rectangle(GD_OBJECT_LEVEL_ALL, x1, y1, x2, y2, elem, bd1_import(data[index+6], index+6)));
960 elem = bd1_import(data[index + 1], index + 1);
961 y1 = data[index + 2];
962 x1 = data[index + 3];
966 Warn("invalid point coordinates %d,%d at byte %d", x1, y1, index);
968 cave->objects = list_append(cave->objects, gd_object_new_point(GD_OBJECT_LEVEL_ALL, x1, y1, elem));
974 elem = bd1_import(data[index + 1], index + 1);
975 y1 = data[index + 2]; // starting pos
976 x1 = data[index + 3];
977 ny = data[index + 4] - 1; // number of elements
978 nx = data[index + 5] - 1;
979 dy = data[index + 6]; // displacement
980 dx = data[index + 7];
981 y2 = y1 + dy * ny; // calculate rectangle
984 // guess this has to be here, after x2,y2 calculation, because of some bugs in imported data
994 Warn("invalid raster coordinates %d,%d %d,%d at byte %d", x1, y1, x2, y2, index);
996 cave->objects = list_append(cave->objects, gd_object_new_raster(GD_OBJECT_LEVEL_ALL, x1, y1, x2, y2, dx, dy, elem));
1002 // profi boulder extension: bitmap
1003 elem = bd1_import(data[index + 1], index + 1);
1004 bytes = data[index + 2]; // number of bytes in bitmap
1006 if (bytes >= cave->w * cave->h / 8)
1007 Warn("invalid bitmap length at byte %d", index - 4);
1010 addr += data[index + 3]; // msb
1011 addr += data[index + 4] << 8; // lsb
1013 // this was a pointer to the cave work memory (used during game).
1016 if (addr >= cave->w * cave->h)
1017 Warn("invalid bitmap start address at byte %d", index - 4);
1022 for (i = 0; i < bytes; i++)
1024 // for ("bytes" number of bytes)
1025 val = data[index + 5 + i];
1027 for (n = 0; n < 8; n++)
1029 // for (8 bits in a byte)
1030 if ((val & 1) != 0) // convert to single points...
1031 cave->objects = list_append(cave->objects, gd_object_new_point(GD_OBJECT_LEVEL_ALL, x1, y1, elem));
1034 x1++; // next cave pos
1038 // maybe next line in map
1045 index += 5 + bytes; // 5 description bytes and "bytes" data bytes
1049 dy = data[index + 3] / 40;
1050 dx = data[index + 3] % 40; // same byte!!!
1051 cave->objects = list_append(cave->objects, gd_object_new_join(GD_OBJECT_LEVEL_ALL, dx, dy, bd1_import(data[index+1], index+1), bd1_import(data[index+2], index+2)));
1056 case 7: // SLIME PERMEABILITY
1057 // interesting this is set here, and not in the cave header
1058 for (i = 0; i < 5; i++)
1059 cave->level_slime_permeability_c64[i] = data[index + 1];
1065 // profi boulder extension by player: plck-like cave map. the import
1066 // routine (any2gdash) inserts it here.
1067 if (cave->map != NULL)
1069 Error("contains more than one PLCK map");
1070 gd_cave_map_free(cave->map);
1073 cave->map = gd_cave_map_new(cave, GdElement);
1075 for (x = 0; x < cave->w; x++)
1077 // fill the first and the last row with steel wall.
1078 cave->map[0][x] = O_STEEL;
1079 cave->map[cave->h - 1][x] = O_STEEL;
1082 n = 0; // number of bytes read from map
1084 // the first and the last rows are not stored.
1085 for (y = 1; y < cave->h - 1; y++)
1087 for (x = 0; x < cave->w; x += 2)
1089 cave->map[y][x] = plck_import_nybble[data[index + 3 + n] >> 4]; // msb 4 bits
1090 cave->map[y][x + 1] = plck_import_nybble[data[index + 3 + n] % 16]; // lsb 4 bits
1095 // the position of inbox is stored. this is to check the cave
1096 ry = data[index + 1] - 2;
1097 rx = data[index + 2];
1099 // at the start of the cave, bd scrolled to the last player placed during the drawing
1100 // (setup) of the cave.
1101 // i think this is why a map also stored the coordinates of the player - we can use
1102 // this to check its integrity
1103 if (rx >= cave->w || ry < 0 ||
1104 ry >= cave->h || cave->map[ry][rx] != O_INBOX)
1105 Warn ("embedded PLCK map may be corrupted, player coordinates %d,%d", rx, rx);
1111 Warn ("unknown bd2 extension no. %02x at byte %d", data[index], index);
1113 index += 1; // skip that byte
1117 if (data[index] != 0xFF)
1119 Error("import error, cave not delimited with 0xFF");
1126 // animation byte - told the engine which objects to animate - to make game faster
1129 // the colors from the memory dump are appended here by any2gdash
1130 if (format == GD_FORMAT_BD2)
1133 cave->color0 = gd_c64_color(0);
1134 cave->color1 = gd_c64_color(data[index + 0] & 0xf);
1135 cave->color2 = gd_c64_color(data[index + 1] & 0xf);
1136 cave->color3 = gd_c64_color(data[index + 2] & 0x7); // lower 3 bits only!
1137 cave->color4 = cave->color1; // in bd2, amoeba was color1
1138 cave->color5 = cave->color1; // slime too
1144 cave->color1 = gd_atari_color(data[index + 0]);
1145 cave->color2 = gd_atari_color(data[index + 1]);
1146 cave->color3 = gd_atari_color(data[index + 2]);
1147 cave->color4 = gd_atari_color(data[index + 3]); // amoeba and slime
1148 cave->color5 = gd_atari_color(data[index + 3]);
1149 cave->colorb = gd_atari_color(data[index + 4]); // background and border
1150 cave->color0 = gd_atari_color(data[index + 4]);
1157 // import plck cave data into our format.
1158 // length is always 512 bytes, and contains if it is an intermission cave.
1159 static int cave_copy_from_plck(GdCave *cave, const byte *data,
1160 int remaining_bytes, GdCavefileFormat format)
1162 // i don't really think that all this table is needed, but included to be complete.
1163 // this is for the dirt and expanding wall looks like effect.
1164 // it also contains the individual frames
1165 static GdElement plck_graphic_table[] =
1167 /* 3000 */ O_UNKNOWN, O_UNKNOWN, O_UNKNOWN, O_UNKNOWN, O_UNKNOWN, O_UNKNOWN, O_UNKNOWN, O_UNKNOWN,
1168 /* 3100 */ O_BUTTER_1, O_MAGIC_WALL, O_PRE_DIA_1, O_PRE_DIA_2, O_PRE_DIA_3, O_PRE_DIA_4, O_PRE_DIA_5, O_OUTBOX_CLOSED,
1169 /* 3200 */ O_AMOEBA, O_VOODOO, O_STONE, O_DIRT, O_DIAMOND, O_STEEL, O_PLAYER, O_BRICK,
1170 /* 3300 */ O_SPACE, O_OUTBOX_OPEN, O_FIREFLY_1, O_EXPLODE_1, O_EXPLODE_2, O_EXPLODE_3, O_MAGIC_WALL, O_MAGIC_WALL,
1171 /* 3400 */ O_PLAYER_TAP_BLINK, O_PLAYER_TAP_BLINK, O_PLAYER_TAP_BLINK, O_PLAYER_TAP_BLINK, O_PLAYER_TAP_BLINK, O_PLAYER_TAP_BLINK, O_PLAYER_TAP_BLINK, O_PLAYER_TAP_BLINK,
1172 /* 3500 */ O_PLAYER_LEFT, O_PLAYER_LEFT, O_PLAYER_LEFT, O_PLAYER_LEFT, O_PLAYER_LEFT, O_PLAYER_LEFT, O_PLAYER_LEFT, O_PLAYER_LEFT,
1173 /* 3600 */ O_PLAYER_RIGHT, O_PLAYER_RIGHT, O_PLAYER_RIGHT, O_PLAYER_RIGHT, O_PLAYER_RIGHT, O_PLAYER_RIGHT, O_PLAYER_RIGHT, O_PLAYER_RIGHT,
1174 /* 3700 */ O_BUTTER_1, O_BUTTER_1, O_BUTTER_1, O_BUTTER_1, O_BUTTER_1, O_BUTTER_1, O_BUTTER_1, O_BUTTER_1,
1175 /* 3800 */ O_AMOEBA, O_AMOEBA, O_AMOEBA, O_AMOEBA, O_AMOEBA, O_AMOEBA, O_AMOEBA, O_AMOEBA,
1181 if (remaining_bytes < 512)
1183 Error("truncated plck cave data!");
1187 gd_cave_set_engine_defaults(cave, GD_ENGINE_PLCK);
1189 if (format == GD_FORMAT_PLC_ATARI)
1190 cave->scheduling = GD_SCHEDULING_BD2_PLCK_ATARI;
1192 cave->intermission = data[0x1da] != 0;
1194 if (cave->intermission)
1196 // set visible size for intermission
1201 // cave selection table, was not part of cave data, rather given in game packers.
1202 // if a new enough version of any2gdash is used, it will put information after the cave.
1203 // detect this here and act accordingly
1204 if ((data[0x1f0] == data[0x1f1] - 1) &&
1205 (data[0x1f0] == 0x19 ||
1206 data[0x1f0] == 0x0e))
1210 // found selection table
1211 cave->selectable = data[0x1f0] == 0x19;
1212 gd_strcpy(cave->name, " ");
1214 for (j = 0; j < 12; j++)
1215 cave->name[j] = data[0x1f2 + j];
1217 chompString(cave->name); // remove spaces
1221 // no selection info found, let intermissions be unselectable
1222 cave->selectable = !cave->intermission;
1225 cave->diamond_value = data[0x1be];
1226 cave->extra_diamond_value = data[0x1c0];
1228 for (i = 0; i < 5; i++)
1230 // plck doesnot really have levels, so just duplicate data five times
1231 cave->level_amoeba_time[i] = data[0x1c4];
1233 // immediately underflowed to 999, so we use 999. example: sendydash 3, cave 02.
1234 if (cave->level_amoeba_time[i] == 0)
1235 cave->level_amoeba_time[i] = 999;
1237 cave->level_time[i] = data[0x1ba];
1238 cave->level_diamonds[i] = data[0x1bc];
1240 // gate opening is checked AFTER adding to diamonds collected, so 0 here is 1000 needed
1241 if (cave->level_diamonds[i] == 0)
1242 cave->level_diamonds[i] = 1000;
1244 cave->level_ckdelay[i] = data[0x1b8];
1245 cave->level_magic_wall_time[i] = data[0x1c6];
1246 cave->level_slime_permeability_c64[i] = slime_shift_msb(data[0x1c2]);
1249 if (format == GD_FORMAT_PLC_ATARI)
1252 cave->colorb = gd_atari_color(0); // border
1253 // indexes in data are not the same order as on c64!!!
1254 cave->color0 = gd_atari_color(data[0x1e3]); // background
1255 cave->color1 = gd_atari_color(data[0x1db]);
1256 cave->color2 = gd_atari_color(data[0x1dd]);
1257 cave->color3 = gd_atari_color(data[0x1df]);
1258 // in atari plck, slime and amoeba could not coexist in the same cave.
1259 // if amoeba was used, the graphics turned to green, and data at 0x1e1 was set to 0xd4.
1260 // if slime was used, graphics to blue, and data at 0x1e1 was set to 0x72.
1261 // these two colors could not be changed in the editor at all.
1262 // (maybe they could have been changed in a hex editor)
1263 cave->color4 = gd_atari_color(data[0x1e1]);
1264 cave->color5 = gd_atari_color(data[0x1e1]);
1269 cave->colorb = gd_c64_color(data[0x1db] & 0xf); // border
1270 cave->color0 = gd_c64_color(data[0x1dd] & 0xf);
1271 cave->color1 = gd_c64_color(data[0x1df] & 0xf);
1272 cave->color2 = gd_c64_color(data[0x1e1] & 0xf);
1273 cave->color3 = gd_c64_color(data[0x1e3] & 0x7); // lower 3 bits only!
1274 cave->color4 = cave->color3; // in plck, amoeba was color3
1275 cave->color5 = cave->color3; // same for slime
1278 // ... the cave is stored like a map.
1279 cave->map = gd_cave_map_new(cave, GdElement);
1281 // cave map looked like this.
1282 // two rows of steel wall ($44's), then cave description, 20 bytes (40 nybbles) for each line.
1283 // the bottom and top lines were not stored... originally.
1284 // some games write to the top line; so we import that, too.
1285 // also dlp 155 allowed writing to the bottom line; the first 20 $44-s now store the bottom line.
1286 // so the cave is essentially shifted one row down in the file:
1287 // cave->map[y][x] = data[... y+1 mod height ][x]
1288 for (y = 0; y < cave->h; y++)
1290 for (x = 0; x < cave->w; x += 2)
1292 // msb 4 bits: we do not check index ranges, as >>4 and %16 will result in 0..15
1293 cave->map[y][x] = plck_import_nybble[data[((y + 1) % cave->h) * 20 + x / 2] >> 4];
1296 cave->map[y][x + 1] = plck_import_nybble[data[((y + 1) % cave->h) * 20 + x / 2] % 16];
1300 // FOR NOW, WE DO NOT IMPORT THE BOTTOM BORDER
1301 for (x = 0; x < cave->w; x++)
1302 cave->map[cave->h - 1][x] = O_STEEL;
1304 // check for diego-effects
1305 // c64 magic values (byte sequences) 0x20 0x90 0x46, also 0xa9 0x1c 0x85
1306 if ((data[0x1e5] == 0x20 && data[0x1e6] == 0x90 && data[0x1e7] == 0x46) ||
1307 (data[0x1e5] == 0xa9 && data[0x1e6] == 0x1c && data[0x1e7] == 0x85))
1309 // diego effects enabled.
1310 cave->stone_bouncing_effect = bd1_import(data[0x1ea], 0x1ea);
1311 cave->diamond_falling_effect = bd1_import(data[0x1eb], 0x1eb);
1313 // explosions: 0x1e was explosion 5, if this is set to default, we also do not read it,
1314 // as in our engine this would cause an O_EXPLODE_5 to stay there.
1315 if (data[0x1ec] != 0x1e)
1316 cave->explosion_effect = bd1_import(data[0x1ec], 0x1ec);
1319 pointer to element graphic.
1320 two bytes/column (one element), that is data[xxx] % 16 / 2.
1321 also there are 16bytes/row.
1322 that is, 0x44 = stone, upper left character. 0x45 = upper right,
1323 0x54 = lower right, 0x55 = lower right.
1324 so high nybble must be shifted right twice -> data[xxx]/16*4.
1326 cave->dirt_looks_like = plck_graphic_table[(data[0x1ed] / 16) * 4 + (data[0x1ed] % 16) / 2];
1327 cave->expanding_wall_looks_like = plck_graphic_table[(data[0x1ee] / 16) * 4 + (data[0x1ee] % 16) / 2];
1329 for (i = 0; i < 5; i++)
1330 cave->level_amoeba_threshold[i] = data[0x1ef];
1336 // no one's delight boulder dash essentially: rle compressed plck maps.
1337 static int cave_copy_from_dlb(GdCave *cave, const byte *data, int remaining_bytes)
1342 START, // initial state
1343 SEPARATOR, // got a separator
1344 RLE, // after a separator, got the byte to duplicate
1345 NORMAL // normal, copy bytes till separator
1347 int pos, cavepos, i, x, y;
1348 byte byte, separator;
1350 gd_cave_set_engine_defaults(cave, GD_ENGINE_PLCK); // essentially the plck engine
1352 for (i = 0; i < 5; i++)
1354 // does not really have levels, so just duplicate data five times
1355 cave->level_time[i] = data[1];
1356 cave->level_diamonds[i] = data[2];
1358 // gate opening is checked AFTER adding to diamonds collected, so 0 here is 1000 needed
1359 if (cave->level_diamonds[i] == 0)
1360 cave->level_diamonds[i] = 1000;
1362 cave->level_ckdelay[i] = data[0];
1363 cave->level_amoeba_time[i] = data[6];
1365 // 0 immediately underflowed to 999, so we use 999. example: sendydash 3, cave 02.
1366 if (cave->level_amoeba_time[i] == 0)
1367 cave->level_amoeba_time[i] = 999;
1369 cave->level_magic_wall_time[i] = data[7];
1370 cave->level_slime_permeability_c64[i] = slime_shift_msb(data[5]);
1373 cave->diamond_value = data[3];
1374 cave->extra_diamond_value = data[4];
1376 // then 5 color bytes follow
1377 cave->colorb = gd_c64_color(data[8] & 0xf); // border
1378 cave->color0 = gd_c64_color(data[9] & 0xf);
1379 cave->color1 = gd_c64_color(data[10] & 0xf);
1380 cave->color2 = gd_c64_color(data[11] & 0xf);
1381 cave->color3 = gd_c64_color(data[12] & 0x7); // lower 3 bits only!
1382 cave->color4 = cave->color3; // in plck, amoeba was color3
1383 cave->color5 = cave->color3; // same for slime
1386 pos = 13; // those 13 bytes were the cave values above
1388 byte = 0; // just to get rid of compiler warning
1389 separator = 0; // just to get rid of compiler warning
1391 // employ a state machine.
1394 while (cavepos < 400 && pos < remaining_bytes)
1399 // first byte is a separator. remember it
1400 separator = data[pos];
1402 // after the first separator, no rle data, just copy.
1407 // we had a separator. remember this byte, as this will be duplicated (or more)
1413 // we had the first byte, duplicate this n times.
1414 if (data[pos] == 0xff)
1416 // if it is a 0xff, we will have another byte, which is also a length specifier.
1417 // and for this one, duplicate only 254 times
1418 if (cavepos + 254 > 400)
1420 Error("DLB import error: RLE data overflows buffer");
1424 for (i = 0; i < 254; i++)
1425 decomp[cavepos++] = byte;
1429 // if not 0xff, duplicate n times and back to copy mode
1430 if (cavepos + data[pos] > 400)
1432 Error("DLB import error: RLE data overflows buffer");
1436 for (i = 0; i < data[pos]; i++)
1437 decomp[cavepos++] = byte;
1444 // bytes duplicated; now only copy the remaining, till the next separator.
1445 if (data[pos] == separator)
1448 decomp[cavepos++] = data[pos]; // copy this byte and state is still NORMAL
1457 Error("DLB import error: RLE processing, cave length %d, should be 400", cavepos);
1461 // process uncompressed map
1462 cave->map = gd_cave_map_new(cave, GdElement);
1464 for (x = 0; x < cave->w; x++)
1466 // fill the first and the last row with steel wall.
1467 cave->map[0][x] = O_STEEL;
1468 cave->map[cave->h - 1][x] = O_STEEL;
1471 for (y = 1; y < cave->h - 1; y++)
1473 for (x = 0; x < cave->w; x += 2)
1476 cave->map[y][x] = plck_import_nybble[decomp[((y - 1) * cave->w + x) / 2] >> 4];
1478 cave->map[y][x + 1] = plck_import_nybble[decomp[((y - 1) * cave->w + x) / 2] % 16];
1482 // return number of bytes read from buffer
1486 // import plck cave data into our format.
1487 static int cave_copy_from_1stb(GdCave *cave, const byte *data, int remaining_bytes)
1492 if (remaining_bytes < 1024)
1494 Error("truncated 1stb cave data!");
1499 gd_cave_set_engine_defaults(cave, GD_ENGINE_1STB);
1502 gd_strcpy(cave->name, " ");
1504 for (i = 0; i < 14; i++)
1506 int c = data[0x3a0 + i];
1508 // import cave name; a conversion table is used for each character
1510 c = gd_bd_internal_chars[c];
1516 c = ' '; // don't know this, so change to space
1524 chompString(cave->name);
1526 cave->intermission = data[0x389] != 0;
1528 // if it is intermission but not scrollable
1529 if (cave->intermission && !data[0x38c])
1535 cave->diamond_value = 100 * data[0x379] + 10 * data[0x379 + 1] + data[0x379 + 2];
1536 cave->extra_diamond_value = 100 * data[0x376] + 10 * data[0x376 + 1] + data[0x376 + 2];
1538 for (i = 0; i < 5; i++)
1540 // plck doesnot really have levels, so just duplicate data five times
1541 cave->level_time[i] = 100 * data[0x370] + 10 * data[0x370+1] + data[0x370 + 2];
1543 // same as gate opening after 0 diamonds
1544 if (cave->level_time[i] == 0)
1545 cave->level_time[i] = 1000;
1547 cave->level_diamonds[i] = 100 * data[0x373] + 10 * data[0x373 + 1] + data[0x373 + 2];
1549 // gate opening is checked AFTER adding to diamonds collected, so 0 here is 1000 (!) needed
1550 if (cave->level_diamonds[i] == 0)
1551 cave->level_diamonds[i] = 1000;
1553 cave->level_ckdelay[i] = data[0x38a];
1554 cave->level_amoeba_time[i] = 256 * (int)data[0x37c] + data[0x37d];
1556 // 0 immediately underflowed to 999, so we use 999. example: sendydash 3, cave 02.
1557 if (cave->level_amoeba_time[i] == 0)
1558 cave->level_amoeba_time[i] = 999;
1560 cave->level_magic_wall_time[i] = 256 * (int)data[0x37e] + data[0x37f];
1561 cave->level_slime_permeability_c64[i] = data[0x38b];
1562 cave->level_bonus_time[i] = data[0x392];
1563 cave->level_penalty_time[i] = data[0x393];
1564 cave->level_amoeba_threshold[i] = 256 * (int)data[0x390] + data[0x390 + 1];
1567 // also has no random data...
1569 cave->colorb = gd_c64_color(data[0x384] & 0xf); // border
1570 cave->color0 = gd_c64_color(data[0x385] & 0xf);
1571 cave->color1 = gd_c64_color(data[0x386] & 0xf);
1572 cave->color2 = gd_c64_color(data[0x387] & 0xf);
1573 cave->color3 = gd_c64_color(data[0x388] & 0x7); // lower 3 bits only!
1574 cave->color4 = cave->color1;
1575 cave->color5 = cave->color1;
1577 cave->amoeba_growth_prob = (4.0 * 1E6 / (data[0x382] + 1)) + 0.5; // probabilities store *1M
1578 if (cave->amoeba_growth_prob > 1000000)
1579 cave->amoeba_growth_prob = 1000000;
1581 cave->amoeba_fast_growth_prob = (4.0 * 1E6 / (data[0x383] + 1)) + 0.5;
1582 if (cave->amoeba_fast_growth_prob > 1000000)
1583 cave->amoeba_fast_growth_prob = 1000000;
1585 if (data[0x380] != 0)
1586 cave->creatures_direction_auto_change_time = data[0x381];
1588 cave->diagonal_movements = data[0x381] != 0;
1590 // ... the cave is stored like a map.
1591 cave->map = gd_cave_map_new(cave, GdElement);
1592 for (y = 0; y < cave->h; y++)
1593 for (x = 0; x < cave->w; x++)
1594 cave->map[y][x] = firstboulder_import(data[y * 40 + x], y * 40 + x);
1596 cave->magic_wall_sound = data[0x38d] == 0xf1;
1598 // 2d was a normal switch, 2e a changed one.
1599 cave->creatures_backwards = data[0x38f] == 0x2d;
1601 // 2e horizontal, 2f vertical.
1602 cave->expanding_wall_changed = data[0x38e] == 0x2f;
1604 cave->biter_delay_frame = data[0x394];
1605 cave->magic_wall_stops_amoeba = data[0x395] == 0; // negated!!
1607 cave->bomb_explosion_effect = firstboulder_import(data[0x396], 0x396);
1608 cave->explosion_effect = firstboulder_import(data[0x397], 0x397);
1609 cave->stone_bouncing_effect = firstboulder_import(data[0x398], 0x398);
1610 cave->diamond_birth_effect = firstboulder_import(data[0x399], 0x399);
1611 cave->magic_diamond_to = firstboulder_import(data[0x39a], 0x39a);
1613 cave->bladder_converts_by = firstboulder_import(data[0x39b], 0x39b);
1614 cave->diamond_falling_effect = firstboulder_import(data[0x39c], 0x39c);
1615 cave->biter_eat = firstboulder_import(data[0x39d], 0x39d);
1616 cave->slime_eats_1 = firstboulder_import(data[0x39e], 0x39e);
1617 cave->slime_converts_1 = firstboulder_import(data[0x39e] + 3, 0x39e);
1618 cave->slime_eats_2 = firstboulder_import(data[0x39f], 0x39f);
1619 cave->slime_converts_2 = firstboulder_import(data[0x39f] + 3, 0x39f);
1620 cave->magic_diamond_to = firstboulder_import(data[0x39a], 0x39a);
1622 // length is always 1024 bytes
1627 static int cave_copy_from_crdr_7(GdCave *cave, const byte *data, int remaining_bytes)
1632 // if we have name, convert
1633 gd_strcpy(cave->name, " ");
1635 for (i = 0; i < 14; i++)
1639 // import cave name; a conversion table is used for each character
1641 c = gd_bd_internal_chars[c];
1654 chompString(cave->name); // remove trailing and leading spaces
1656 cave->selectable = data[14] != 0;
1658 // jump 15 bytes, 14 was the name and 15 selectability
1661 if (memcmp((char *)data + 0x30, "V4\0020", 4) != 0)
1662 Warn("unknown crdr version %c%c%c%c", data[0x30], data[0x31], data[0x32], data[0x33]);
1664 gd_cave_set_engine_defaults(cave, GD_ENGINE_CRDR7);
1666 for (i = 0; i < 5; i++)
1668 cave->level_time[i] = (int)data[0x0] * 100 + data[0x1] * 10 + data[0x2];
1670 // same as gate opening after 0 diamonds
1671 if (cave->level_time[i] == 0)
1672 cave->level_time[i] = 1000;
1674 cave->level_diamonds[i] = (int)data[0x3] * 100 + data[0x4] * 10 + data[0x5];
1676 // gate opening is checked AFTER adding to diamonds collected, so 0 here is 1000 (!) needed
1677 if (cave->level_diamonds[i] == 0)
1678 cave->level_diamonds[i] = 1000;
1680 cave->level_ckdelay[i] = data[0x1A];
1681 cave->level_rand[i] = data[0x40];
1682 cave->level_amoeba_time[i] = (int)data[0xC] * 256 + data[0xD];
1684 // 0 immediately underflowed to 999, so we use 999. example: sendydash 3, cave 02.
1685 if (cave->level_amoeba_time[i] == 0)
1686 cave->level_amoeba_time[i] = 999;
1688 cave->level_magic_wall_time[i] = (int)data[0xE] * 256 + data[0xF];
1689 cave->level_slime_permeability_c64[i] = data[0x1B];
1690 cave->level_bonus_time[i] = data[0x22];
1691 cave->level_penalty_time[i] = data[0x23];
1692 cave->level_bonus_time[i] = data[0x22];
1693 cave->level_penalty_time[i] = data[0x23];
1694 cave->level_amoeba_threshold[i] = 256 * (int)data[0x20] + data[0x21];
1697 cave->extra_diamond_value = (int)data[0x6] * 100 + data[0x7] * 10 + data[0x8];
1698 cave->diamond_value = (int)data[0x9] * 100 + data[0xA] * 10 + data[0xB];
1701 cave->creatures_direction_auto_change_time = data[0x11];
1703 cave->colorb = gd_c64_color(data[0x14] & 0xf); // border
1704 cave->color0 = gd_c64_color(data[0x15] & 0xf);
1705 cave->color1 = gd_c64_color(data[0x16] & 0xf);
1706 cave->color2 = gd_c64_color(data[0x17] & 0xf);
1707 cave->color3 = gd_c64_color(data[0x18] & 0x7); // lower 3 bits only!
1708 cave->color4 = cave->color3;
1709 cave->color5 = cave->color1;
1711 cave->intermission = data[0x19] != 0;
1713 // if it is intermission but not scrollable
1714 if (cave->intermission && !data[0x1c])
1721 AMOEBA in crazy dash 8:
1722 jsr $2500 ; generate true random
1723 and $94 ; binary and the current "probability"
1724 cmp #$04 ; compare to 4
1725 bcs out ; jump out (do not expand) if carry set, ie. result was less than 4.
1727 prob values can be like num = 3, 7, 15, 31, 63, ... n lsb bits count.
1728 0..3>=4? 0..7>=4? 0..15>=4? and similar.
1729 this way, probability of growing is 4/(num+1)
1732 cave->amoeba_growth_prob = (4.0 * 1E6 / (data[0x12] + 1)) + 0.5; // probabilities store * 1M
1733 if (cave->amoeba_growth_prob > 1000000)
1734 cave->amoeba_growth_prob = 1000000;
1736 cave->amoeba_fast_growth_prob = (4.0 * 1E6 / (data[0x13] + 1)) + 0.5;
1737 if (cave->amoeba_fast_growth_prob > 1000000)
1738 cave->amoeba_fast_growth_prob = 1000000;
1740 // expanding wall direction change - 2e horizontal, 2f vertical
1741 cave->expanding_wall_changed = data[0x1e] == 0x2f;
1743 // 2c was a normal switch, 2d a changed one.
1744 cave->creatures_backwards = data[0x1f] == 0x2d;
1745 cave->biter_delay_frame = data[0x24];
1746 cave->magic_wall_stops_amoeba = data[0x25] == 0; // negated!!
1748 cave->bomb_explosion_effect = crazydream_import_table[data[0x26]];
1749 cave->explosion_effect = crazydream_import_table[data[0x27]];
1750 cave->stone_bouncing_effect = crazydream_import_table[data[0x28]];
1751 cave->diamond_birth_effect = crazydream_import_table[data[0x29]];
1752 cave->magic_diamond_to = crazydream_import_table[data[0x2a]];
1754 cave->bladder_converts_by = crazydream_import_table[data[0x2b]];
1755 cave->diamond_falling_effect = crazydream_import_table[data[0x2c]];
1756 cave->biter_eat = crazydream_import_table[data[0x2d]];
1757 cave->slime_eats_1 = crazydream_import_table[data[0x2e]];
1758 cave->slime_converts_1 = crazydream_import_table[data[0x2e] + 3];
1759 cave->slime_eats_2 = crazydream_import_table[data[0x2f]];
1760 cave->slime_converts_2 = crazydream_import_table[data[0x2f] + 3];
1762 cave->diagonal_movements = (data[0x34] & 1) != 0;
1763 cave->gravity_change_time = data[0x35];
1764 cave->pneumatic_hammer_frame = data[0x36];
1765 cave->hammered_wall_reappear_frame = data[0x37];
1766 cave->hammered_walls_reappear = data[0x3f] != 0;
1769 acid in crazy dream 8:
1770 jsr $2500 ; true random
1771 cmp $03a8 ; compare to ratio
1772 bcs out ; if it was smaller, forget it for now.
1774 ie. random<=ratio, then acid grows.
1777 // 1e6, probabilities are stored as int
1778 cave->acid_spread_ratio = data[0x38] / 255.0 * 1E6 + 0.5;
1780 cave->acid_eats_this = crazydream_import_table[data[0x39]];
1781 switch(data[0x3a] & 3)
1783 case 0: cave->gravity = GD_MV_UP; break;
1784 case 1: cave->gravity = GD_MV_DOWN; break;
1785 case 2: cave->gravity = GD_MV_LEFT; break;
1786 case 3: cave->gravity = GD_MV_RIGHT; break;
1789 cave->snap_element = ((data[0x3a] & 4) != 0) ? O_EXPLODE_1 : O_SPACE;
1791 // we do not know the values for these, so do not import
1792 // cave->dirt_looks_like... data[0x3c]
1793 // cave->expanding_wall_looks_like... data[0x3b]
1794 for (i = 0; i < 4; i++)
1796 cave->random_fill[i] = crazydream_import_table[data[0x41 + i]];
1797 cave->random_fill_probability[i] = data[0x45 + i];
1803 while (data[index] != 0xff)
1806 int x1, y1, x2, y2, dx, dy;
1808 int length, direction;
1810 // for copy&paste; copy&paste are different objects, static = ugly solution :)
1811 static int cx1, cy1, cw, ch;
1813 switch (data[index])
1816 elem = crazydream_import_table[data[index + 1]];
1817 x1 = data[index + 2];
1818 y1 = data[index + 3];
1819 if (x1 >= cave->w || y1 >= cave->h)
1820 Warn("invalid point coordinates %d,%d at byte %d", x1, y1, index);
1822 cave->objects = list_append(cave->objects, gd_object_new_point(GD_OBJECT_LEVEL_ALL, x1, y1, elem));
1827 case 2: // rectangle
1828 elem = crazydream_import_table[data[index + 1]];
1829 x1 = data[index + 2];
1830 y1 = data[index + 3];
1831 x2 = x1 + data[index + 4] - 1;
1832 y2 = y1 + data[index + 5] - 1; // height
1834 if (x1 >= cave->w ||
1838 Warn("invalid rectangle coordinates %d,%d %d,%d at byte %d", x1, y1, x2, y2, index);
1840 cave->objects = list_append(cave->objects, gd_object_new_rectangle(GD_OBJECT_LEVEL_ALL, x1, y1, x2, y2, elem));
1846 x1 = data[index + 2];
1847 y1 = data[index + 3];
1848 x2 = x1 + data[index + 4] - 1;
1849 y2 = y1 + data[index + 5] - 1;
1851 if (x1 >= cave->w ||
1855 Warn("invalid filled rectangle coordinates %d,%d %d,%d at byte %d", x1, y1, x2, y2, index);
1857 // border and inside of fill is the same element.
1858 cave->objects = list_append(cave->objects, gd_object_new_filled_rectangle(GD_OBJECT_LEVEL_ALL, x1, y1, x2, y2, crazydream_import_table[data[index + 1]], crazydream_import_table[data[index + 1]]));
1864 elem = crazydream_import_table[data[index + 1]];
1865 if (elem == O_UNKNOWN)
1866 Warn("unknown element at %d: %x", index + 1, data[index + 1]);
1868 x1 = data[index + 2];
1869 y1 = data[index + 3];
1870 length = data[index + 4];
1871 direction = data[index + 5];
1872 nx = ((signed)direction - 128) % 40;
1873 ny = ((signed)direction - 128) / 40;
1874 x2 = x1 + (length - 1) * nx;
1875 y2 = y1 + (length - 1) * ny;
1877 // if either is bigger than one, we cannot treat this as a line. create points instead
1878 if (ABS(nx) >= 2 || ABS(ny) >= 2)
1880 for (i = 0; i < length; i++)
1882 cave->objects = list_append(cave->objects, gd_object_new_point(GD_OBJECT_LEVEL_ALL, x1, y1, elem));
1889 // this is a normal line, and will be appended. only do the checking here
1890 if (x1 >= cave->w ||
1894 Warn("invalid line coordinates %d,%d %d,%d at byte %d", x1, y1, x2, y2, index - 5);
1896 cave->objects = list_append(cave->objects, gd_object_new_line(GD_OBJECT_LEVEL_ALL, x1, y1, x2, y2, elem));
1903 cx1 = data[index + 1];
1904 cy1 = data[index + 2];
1905 cw = data[index + 3];
1906 ch = data[index + 4];
1908 if (cx1 >= cave->w ||
1910 cx1 + cw > cave->w ||
1912 Warn("invalid copy coordinates %d,%d or size %d,%d at byte %d", cx1, cy1, cw, ch, index);
1921 // original stored width and height, we store the coordinates of the source area
1924 dx = data[index + 1]; // new pos
1925 dy = data[index + 2];
1927 if (dx >= cave->w ||
1929 dx + cw > cave->w ||
1931 Warn("invalid paste coordinates %d,%d at byte %d", dx, dy, index);
1933 cave->objects = list_append(cave->objects, gd_object_new_copy_paste(GD_OBJECT_LEVEL_ALL, x1, y1, x2, y2, dx, dy, FALSE, FALSE));
1939 elem = crazydream_import_table[data[index + 1]];
1940 x1 = data[index + 2];
1941 y1 = data[index + 3];
1942 dx = data[index + 4];
1943 dy = data[index + 5];
1944 nx = data[index + 6] - 1;
1945 ny = data[index + 7] - 1;
1946 x2 = x1 + dx * nx; // calculate rectangle we use
1954 if (x1 >= cave->w ||
1958 Warn("invalid raster coordinates %d,%d %d,%d at byte %d", x1, y1, x2, y2, index);
1960 cave->objects = list_append(cave->objects, gd_object_new_raster(GD_OBJECT_LEVEL_ALL, x1, y1, x2, y2, dx, dy, elem));
1966 Warn ("unknown crdr extension no. %02x at byte %d", data[index], index);
1967 index += 1; // skip that byte
1972 index++; // skip $ff
1974 // crazy dream 7 hack
1977 for (i = 0; i < 0x3b0; i++)
1978 checksum = checksum^data[i];
1980 if (strEqual(cave->name, "Crazy maze") && checksum == 195)
1981 cave->skeletons_needed_for_pot = 0;
1983 return 15 + 0x49 + index;
1986 static void crazy_dream_9_add_specials(GdCave *cave, const byte *buf, const int length)
1991 // crazy dream 9 hack
1993 for (i = 0; i < length; i++)
1994 checksum = checksum^buf[i];
1996 // check cave name and the checksum. both are hardcoded here
1997 if (strEqual(cave->name, "Rockfall") && checksum == 134)
1999 GdElement rand[4] = { O_DIAMOND, O_STONE, O_ACID, O_DIRT };
2000 int prob[4] = { 37, 32, 2, 0 };
2001 int seeds[5] = { -1, -1, -1, -1, -1 };
2004 list_append(cave->objects,
2005 gd_object_new_random_fill(GD_OBJECT_LEVEL_ALL, 0, 0, 39, 21, seeds,
2006 O_DIRT, rand, prob, O_BLADDER_SPENDER, FALSE));
2009 if (strEqual(cave->name, "Roll dice now!") && checksum == 235)
2011 GdElement rand[4] = { O_STONE, O_BUTTER_3, O_DIRT, O_DIRT };
2012 int prob[4] = { 0x18, 0x08, 0, 0 };
2013 int seeds[5] = { -1, -1, -1, -1, -1 };
2016 list_append(cave->objects,
2017 gd_object_new_random_fill(GD_OBJECT_LEVEL_ALL, 0, 0, 39, 21, seeds,
2018 O_DIRT, rand, prob, O_BLADDER_SPENDER, FALSE));
2021 if (strEqual(cave->name, "Random maze") && checksum == 24)
2023 int seeds[5] = { -1, -1, -1, -1, -1 };
2025 list_append(cave->objects,
2026 gd_object_new_maze(GD_OBJECT_LEVEL_ALL, 1, 4, 35, 20, 1, 1,
2027 O_NONE, O_DIRT, 50, seeds));
2030 if (strEqual(cave->name, "Metamorphosis") && checksum == 53)
2032 int seeds[5] = { -1, -1, -1, -1, -1 };
2033 GdElement rand[4] = { O_STONE, O_DIRT, O_DIRT, O_DIRT };
2034 int prob[4] = { 0x18, 0, 0, 0 };
2037 list_append(cave->objects,
2038 gd_object_new_maze(GD_OBJECT_LEVEL_ALL, 4, 1, 38, 19, 1, 3,
2039 O_NONE, O_BLADDER_SPENDER, 50, seeds));
2042 list_append(cave->objects,
2043 gd_object_new_random_fill(GD_OBJECT_LEVEL_ALL, 4, 1, 38, 19, seeds,
2044 O_DIRT, rand, prob, O_BLADDER_SPENDER, FALSE));
2046 cave->creatures_backwards = TRUE; // for some reason, this level worked like that
2049 if (strEqual(cave->name, "All the way") && checksum == 33)
2051 int seeds[5] = { -1, -1, -1, -1, -1 };
2054 list_append(cave->objects,
2055 gd_object_new_maze_unicursal(GD_OBJECT_LEVEL_ALL, 1, 1, 35, 19, 1, 1,
2056 O_BRICK, O_PRE_DIA_1, 50, seeds));
2058 // a point which "breaks" the unicursal maze, making it one very long path
2060 list_append(cave->objects, gd_object_new_point(GD_OBJECT_LEVEL_ALL, 35, 18, O_BRICK));
2064 // crazy light contruction kit
2065 static int cave_copy_from_crli(GdCave *cave, const byte *data, int remaining_bytes)
2067 byte uncompressed[1024];
2068 int datapos, cavepos, i, x, y;
2070 const char *versions[] = { "V2.2", "V2.6", "V3.0" };
2074 V2_2, // XXX whats the difference between 2.2 and 2.6?
2078 GdElement (*import) (byte c, int i) = NULL; // import function
2080 gd_cave_set_engine_defaults(cave, GD_ENGINE_CRLI);
2082 // detect if this is a cavefile
2089 datapos = 5; // cavefile, skipping 0x00 0xc4 D L P
2094 // converted from snapshot, skip "selectable" and 14byte name
2099 // if we have name, convert
2102 gd_strcpy(cave->name, " ");
2104 for (i = 0; i < 14; i++)
2106 int c = data[i + 1];
2108 // import cave name; a conversion table is used for each character
2110 c = gd_bd_internal_chars[c];
2124 chompString(cave->name); // remove trailing and leading spaces
2127 // uncompress rle data
2130 while (cavepos < 0x3b0)
2132 // <- loop until the uncompressed reaches its size
2133 if (datapos >= remaining_bytes)
2135 Error("truncated crli cave data");
2139 if (data[datapos] == 0xbf)
2141 // magic value 0xbf is the escape byte
2142 if (datapos + 2 >= remaining_bytes)
2144 Error("truncated crli cave data");
2148 if (data[datapos + 2] + datapos >= sizeof(uncompressed))
2150 // we would run out of buffer, this must be some error
2151 Error("invalid crli cave data - RLE length value is too big");
2155 // 0xbf, number, byte to dup
2156 for (i = 0; i < data[datapos + 2]; i++)
2157 uncompressed[cavepos++] = data[datapos + 1];
2163 uncompressed[cavepos++] = data[datapos++];
2167 // check crli version
2168 for (i = 0; i < ARRAY_SIZE(versions); i++)
2169 if (memcmp((char *)uncompressed + 0x3a0, versions[i], 4) == 0)
2172 // v3.0 has falling wall and box, and no ghost.
2173 import = version >= V3_0 ? crazylight_import : firstboulder_import;
2175 if (version == none)
2177 Warn("unknown crli version %c%c%c%c", uncompressed[0x3a0], uncompressed[0x3a1], uncompressed[0x3a2], uncompressed[0x3a3]);
2178 import = crazylight_import;
2182 cave->map = gd_cave_map_new(cave, GdElement);
2184 for (y = 0; y < cave->h; y++)
2186 for (x = 0; x < cave->w; x++)
2188 int index = y * cave->w + x;
2190 cave->map[y][x] = import(uncompressed[index], index);
2194 // crli has no levels
2195 for (i = 0; i < 5; i++)
2197 cave->level_time[i] = (int)uncompressed[0x370] * 100 + uncompressed[0x371] * 10 + uncompressed[0x372];
2199 // same as gate opening after 0 diamonds
2200 if (cave->level_time[i] == 0)
2201 cave->level_time[i] = 1000;
2203 cave->level_diamonds[i] = (int)uncompressed[0x373] * 100 + uncompressed[0x374] * 10 + uncompressed[0x375];
2205 // gate opening is checked AFTER adding to diamonds collected, so 0 here is 1000 (!) needed
2206 if (cave->level_diamonds[i] == 0)
2207 cave->level_diamonds[i] = 1000;
2209 cave->level_ckdelay[i] = uncompressed[0x38A];
2210 cave->level_amoeba_time[i] = (int)uncompressed[0x37C] * 256 + uncompressed[0x37D];
2212 // 0 immediately underflowed to 999, so we use 999. example: sendydash 3, cave 02.
2213 if (cave->level_amoeba_time[i] == 0)
2214 cave->level_amoeba_time[i] = 999;
2216 cave->level_magic_wall_time[i] = (int)uncompressed[0x37E] * 256 + uncompressed[0x37F];
2217 cave->level_slime_permeability_c64[i] = uncompressed[0x38B];
2218 cave->level_bonus_time[i] = uncompressed[0x392];
2219 cave->level_penalty_time[i] = uncompressed[0x393];
2220 cave->level_amoeba_threshold[i] = 256 * (int)uncompressed[0x390] + uncompressed[0x390 + 1];
2223 cave->extra_diamond_value = (int)uncompressed[0x376] * 100 + uncompressed[0x377] * 10 + uncompressed[0x378];
2224 cave->diamond_value = (int)uncompressed[0x379] * 100 + uncompressed[0x37A] * 10 + uncompressed[0x37B];
2226 if (uncompressed[0x380])
2227 cave->creatures_direction_auto_change_time = uncompressed[0x381];
2229 cave->colorb = gd_c64_color(uncompressed[0x384] & 0xf); // border
2230 cave->color0 = gd_c64_color(uncompressed[0x385] & 0xf);
2231 cave->color1 = gd_c64_color(uncompressed[0x386] & 0xf);
2232 cave->color2 = gd_c64_color(uncompressed[0x387] & 0xf);
2233 cave->color3 = gd_c64_color(uncompressed[0x388] & 0x7); // lower 3 bits only!
2234 cave->color4 = cave->color3;
2235 cave->color5 = cave->color1;
2237 cave->intermission = uncompressed[0x389] != 0;
2239 // if it is intermission but not scrollable
2240 if (cave->intermission && !uncompressed[0x38c])
2247 AMOEBA in crazy dash 8:
2248 jsr $2500 ; generate true random
2249 and $94 ; binary and the current "probability"
2250 cmp #$04 ; compare to 4
2251 bcs out ; jump out (do not expand) if carry set, ie. result was less than 4.
2253 prob values can be like num = 3, 7, 15, 31, 63, ... n lsb bits count.
2254 0..3>=4? 0..7>=4? 0..15>=4? and similar.
2255 this way, probability of growing is 4/(num+1)
2258 // probabilities store * 1M
2259 cave->amoeba_growth_prob = (1E6 * 4.0 / (uncompressed[0x382] + 1)) + 0.5;
2261 if (cave->amoeba_growth_prob > 1000000)
2262 cave->amoeba_growth_prob = 1000000;
2264 cave->amoeba_fast_growth_prob = (1E6*4.0/(uncompressed[0x383] + 1)) + 0.5;
2266 if (cave->amoeba_fast_growth_prob > 1000000)
2267 cave->amoeba_fast_growth_prob = 1000000;
2269 // 2c was a normal switch, 2d a changed one.
2270 cave->creatures_backwards = uncompressed[0x38f] == 0x2d;
2271 cave->magic_wall_sound = uncompressed[0x38d] == 0xf1;
2273 // 2e horizontal, 2f vertical. we implement this by changing them
2274 if (uncompressed[0x38e] == 0x2f)
2276 for (y = 0; y < cave->h; y++)
2278 for (x = 0; x < cave->w; x++)
2280 if (cave->map[y][x] == O_H_EXPANDING_WALL)
2281 cave->map[y][x] = O_V_EXPANDING_WALL;
2286 cave->biter_delay_frame = uncompressed[0x394];
2287 cave->magic_wall_stops_amoeba = uncompressed[0x395] == 0; // negated!!
2288 cave->bomb_explosion_effect = import(uncompressed[0x396], 0x396);
2289 cave->explosion_effect = import(uncompressed[0x397], 0x397);
2290 cave->stone_bouncing_effect = import(uncompressed[0x398], 0x398);
2291 cave->diamond_birth_effect = import(uncompressed[0x399], 0x399);
2292 cave->magic_diamond_to = import(uncompressed[0x39a], 0x39a);
2294 cave->bladder_converts_by = import(uncompressed[0x39b], 0x39b);
2295 cave->diamond_falling_effect = import(uncompressed[0x39c], 0x39c);
2296 cave->biter_eat = import(uncompressed[0x39d], 0x39d);
2297 cave->slime_eats_1 = import(uncompressed[0x39e], 0x39e);
2298 cave->slime_converts_1 = import(uncompressed[0x39e] + 3, 0x39e);
2299 cave->slime_eats_2 = import(uncompressed[0x39f], 0x39f);
2300 cave->slime_converts_2 = import(uncompressed[0x39f] + 3, 0x39f);
2302 // v3.0 has some new properties.
2303 if (version >= V3_0)
2305 cave->diagonal_movements = uncompressed[0x3a4] != 0;
2306 cave->amoeba_too_big_effect = import(uncompressed[0x3a6], 0x3a6);
2307 cave->amoeba_enclosed_effect = import(uncompressed[0x3a7], 0x3a7);
2310 acid in crazy dream 8:
2311 jsr $2500 ; true random
2312 cmp $03a8 ; compare to ratio
2313 bcs out ; if it was smaller, forget it for now.
2315 ie. random<=ratio, then acid grows.
2318 // * 1e6, probabilities are stored as int
2319 cave->acid_spread_ratio = uncompressed[0x3a8] / 255.0 * 1E6;
2320 cave->acid_eats_this = import(uncompressed[0x3a9], 0x3a9);
2321 cave->expanding_wall_looks_like = import(uncompressed[0x3ab], 0x3ab);
2322 cave->dirt_looks_like = import(uncompressed[0x3ac], 0x3ac);
2326 // version is <= 3.0, so this is a 1stb cave.
2327 // the only parameters, for which this matters, are these:
2328 if (uncompressed[0x380] != 0)
2329 cave->creatures_direction_auto_change_time = uncompressed[0x381];
2331 cave->diagonal_movements = uncompressed[0x381] != 0;
2335 cave->selectable = !cave->intermission; // best we can do
2337 cave->selectable = !data[0]; // given by converter
2342 GdCavefileFormat gd_caveset_imported_get_format(const byte *buf)
2344 const char *s_bd1 = "GDashBD1";
2345 const char *s_bd1_atari = "GDashB1A";
2346 const char *s_dc1 = "GDashDC1";
2347 const char *s_bd2 = "GDashBD2";
2348 const char *s_bd2_atari = "GDashB2A";
2349 const char *s_plc = "GDashPLC";
2350 const char *s_plc_atari = "GDashPCA";
2351 const char *s_dlb = "GDashDLB";
2352 const char *s_crl = "GDashCRL";
2353 const char *s_cd7 = "GDashCD7";
2354 const char *s_cd9 = "GDashCD9";
2355 const char *s_1st = "GDash1ST";
2357 if (memcmp((char *)buf, s_bd1, strlen(s_bd1)) == 0)
2358 return GD_FORMAT_BD1;
2359 if (memcmp((char *)buf, s_bd1_atari, strlen(s_bd1_atari)) == 0)
2360 return GD_FORMAT_BD1_ATARI;
2361 if (memcmp((char *)buf, s_dc1, strlen(s_dc1)) == 0)
2362 return GD_FORMAT_DC1;
2363 if (memcmp((char *)buf, s_bd2, strlen(s_bd2)) == 0)
2364 return GD_FORMAT_BD2;
2365 if (memcmp((char *)buf, s_bd2_atari, strlen(s_bd2_atari)) == 0)
2366 return GD_FORMAT_BD2_ATARI;
2367 if (memcmp((char *)buf, s_plc, strlen(s_plc)) == 0)
2368 return GD_FORMAT_PLC;
2369 if (memcmp((char *)buf, s_plc_atari, strlen(s_plc_atari)) == 0)
2370 return GD_FORMAT_PLC_ATARI;
2371 if (memcmp((char *)buf, s_dlb, strlen(s_dlb)) == 0)
2372 return GD_FORMAT_DLB;
2373 if (memcmp((char *)buf, s_crl, strlen(s_crl)) == 0)
2374 return GD_FORMAT_CRLI;
2375 if (memcmp((char *)buf, s_cd7, strlen(s_cd7)) == 0)
2376 return GD_FORMAT_CRDR_7;
2377 if (memcmp((char *)buf, s_cd9, strlen(s_cd9)) == 0)
2378 return GD_FORMAT_CRDR_9;
2379 if (memcmp((char *)buf, s_1st, strlen(s_1st)) == 0)
2380 return GD_FORMAT_FIRSTB;
2382 return GD_FORMAT_UNKNOWN;
2386 // ----------------------------------------------------------------------------
2387 // Load caveset from memory buffer.
2388 // Loads the caveset from a memory buffer.
2389 // returns: List * of caves.
2390 // ----------------------------------------------------------------------------
2392 List *gd_caveset_import_from_buffer (const byte *buf, size_t length)
2395 int cavenum, intermissionnum, num;
2396 int cavelength, bufp;
2397 List *caveset = NULL, *iter;
2398 unsigned int encodedlength;
2399 GdCavefileFormat format;
2401 if (length != -1 && length < 12)
2403 Warn("buffer too short to be a GDash datafile");
2407 encodedlength = (unsigned int)(*((unsigned int *)(buf + 8)));
2408 if (length != -1 && encodedlength != length - 12)
2410 Warn("file length and data size mismatch in GDash datafile");
2414 format = gd_caveset_imported_get_format(buf);
2415 if (format == GD_FORMAT_UNKNOWN)
2417 Warn("buffer does not contain a GDash datafile");
2422 length = encodedlength;
2427 while (bufp < length)
2430 // default is to append cave to caveset; list_insert appends when pos = -1
2433 newcave = gd_cave_new();
2435 cavelength = 0; // to avoid compiler warning
2439 case GD_FORMAT_BD1: // boulder dash 1
2440 case GD_FORMAT_BD1_ATARI: // boulder dash 1, atari version
2441 case GD_FORMAT_DC1: // deluxe caves 1
2442 case GD_FORMAT_BD2: // boulder dash 2
2443 case GD_FORMAT_BD2_ATARI: // boulder dash 2
2444 // these are not in the data so we guess
2445 newcave->selectable = (cavenum < 16) && (cavenum % 4 == 0);
2446 newcave->intermission = cavenum > 15;
2448 // no name, so we make up one
2449 if (newcave->intermission)
2450 snprintf(newcave->name, sizeof(newcave->name), _("Intermission %d"), cavenum - 15);
2452 snprintf(newcave->name, sizeof(newcave->name), _("Cave %c"), 'A' + cavenum);
2457 case GD_FORMAT_BD1_ATARI:
2459 cavelength = cave_copy_from_bd1(newcave, buf + bufp, length - bufp, format);
2462 case GD_FORMAT_BD2_ATARI:
2463 cavelength = cave_copy_from_bd2(newcave, buf + bufp, length - bufp, format);
2470 // original bd1 had level order ABCDEFGH... and then the last four were the intermissions.
2471 // those should be inserted between D-E, H-I... caves.
2473 insertpos = (cavenum - 15) * 5 - 1;
2476 case GD_FORMAT_FIRSTB:
2477 cavelength = cave_copy_from_1stb(newcave, buf + bufp, length - bufp);
2479 // every fifth cave (4+1 intermission) is selectable.
2480 newcave->selectable = cavenum % 5 == 0;
2483 case GD_FORMAT_PLC: // peter liepa construction kit
2484 case GD_FORMAT_PLC_ATARI: // peter liepa construction kit, atari version
2485 cavelength = cave_copy_from_plck(newcave, buf + bufp, length - bufp, format);
2489 // no one's delight boulder dash, something like rle compressed plck caves
2490 // but there are 20 of them, as if it was a bd1 or bd2 game.
2491 // also num%5 = 4 is intermission.
2492 // we have to set intermission flag on our own, as the file did not contain
2493 // the info explicitly
2495 newcave->intermission = (cavenum % 5) == 4;
2496 if (newcave->intermission)
2498 // also set visible size
2503 newcave->selectable = cavenum % 5 == 0; // original selection scheme
2504 if (newcave->intermission)
2505 snprintf(newcave->name, sizeof(newcave->name), _("Intermission %d"), cavenum / 5 + 1);
2507 snprintf(newcave->name, sizeof(newcave->name), _("Cave %c"), 'A'+(cavenum % 5 + cavenum / 5 * 4));
2509 cavelength = cave_copy_from_dlb (newcave, buf + bufp, length - bufp);
2512 case GD_FORMAT_CRLI:
2513 cavelength = cave_copy_from_crli (newcave, buf + bufp, length - bufp);
2516 case GD_FORMAT_CRDR_7:
2517 cavelength = cave_copy_from_crdr_7 (newcave, buf + bufp, length - bufp);
2520 case GD_FORMAT_CRDR_9:
2521 cavelength = cave_copy_from_crli (newcave, buf + bufp, length - bufp);
2522 if (cavelength != -1)
2523 crazy_dream_9_add_specials(newcave, buf, cavelength);
2526 case GD_FORMAT_UNKNOWN:
2530 if (cavelength == -1)
2532 gd_cave_free(newcave);
2534 Error("Aborting cave import.");
2539 caveset = list_insert(caveset, newcave, insertpos);
2545 // hack: some dlb files contain junk data after 20 caves.
2546 if (format == GD_FORMAT_DLB && cavenum == 20)
2549 Warn("excess data in dlb file, %d bytes", (int)(length-bufp));
2554 // try to detect if plc caves are in standard layout.
2555 // that is, caveset looks like an original, (4 cave,1 intermission)+
2556 if (format == GD_FORMAT_PLC)
2557 // if no selection table stored by any2gdash
2558 if ((buf[2 + 0x1f0] != buf[2 + 0x1f1] - 1) ||
2559 (buf[2 + 0x1f0] != 0x19 && buf[2 + 0x1f0] != 0x0e))
2565 standard = (list_length(caveset)%5) == 0; // cave count % 5 != 0 -> nonstandard
2567 for (n = 0, iter = caveset; iter != NULL; n++, iter = iter->next)
2569 GdCave *cave = iter->data;
2571 if ((n % 5 == 4 && !cave->intermission) ||
2572 (n % 5 != 4 && cave->intermission))
2573 standard = FALSE; // 4 cave, 1 intermission
2576 // if test passed, update selectability
2578 for (n = 0, iter = caveset; iter != NULL; n++, iter = iter->next)
2580 GdCave *cave = iter->data;
2582 // update "selectable"
2583 cave->selectable = (n % 5) == 0;
2587 // try to give some names for the caves
2589 intermissionnum = 1;
2592 // use numbering instead of letters, if following formats or too many caves
2593 // (as we would run out of letters)
2594 numbering = format == GD_FORMAT_PLC || format == GD_FORMAT_CRLI || list_length(caveset) > 26;
2596 for (iter = caveset; iter != NULL; iter = iter->next)
2598 GdCave *cave = (GdCave *)iter->data;
2600 if (!strEqual(cave->name, "")) // if it already has a name, skip
2603 if (cave->intermission)
2607 snprintf(cave->name, sizeof(cave->name), _("Intermission %02d"), num);
2609 snprintf(cave->name, sizeof(cave->name), _("Intermission %d"), intermissionnum);
2612 snprintf(cave->name, sizeof(cave->name), _("Cave %02d"), num);
2614 snprintf(cave->name, sizeof(cave->name), _("Cave %c"), 'A' - 1 + cavenum);
2618 if (cave->intermission)
2624 // if the user requests, we make all caves selectable. intermissions not.
2625 if (gd_import_as_all_caves_selectable)
2627 for (iter = caveset; iter != NULL; iter = iter->next)
2629 GdCave *cave = (GdCave *)iter->data;
2631 // make selectable if not an intermission.
2632 // also selectable, if it was selectable originally, for some reason.
2633 cave->selectable = cave->selectable || !cave->intermission;
2640 // to be called at program start.
2641 void gd_c64_import_init_tables(void)