f878472e949f9852e0b5c16d7a91202340827ca5
[rocksndiamonds.git] / src / game_bd / bd_c64import.c
1 /*
2  * Copyright (c) 2007, 2008, 2009, Czirkos Zoltan <cirix@fw.hu>
3  *
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.
7  *
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.
15  */
16
17 #include "main_bd.h"
18
19
20 /* make all caves selectable. */
21 static boolean gd_import_as_all_caves_selectable = TRUE;
22
23 /* conversion table for imported bd1 caves. */
24 static const GdElement bd1_import_table[] =
25 {
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   /* 18 */ O_ACID, O_ACID, O_EXPLODE_1, O_EXPLODE_2,    /* ACID: marek roth extension in crazy dream 3 */
33   /* 1c */ O_EXPLODE_3, O_EXPLODE_4, O_EXPLODE_5, O_PRE_DIA_1,
34   /* 20 */ O_PRE_DIA_2, O_PRE_DIA_3, O_PRE_DIA_4, O_PRE_DIA_5,
35   /* 24 */ O_PRE_DIA_5, O_INBOX, O_PRE_PL_1, O_PRE_PL_2,
36   /* 28 */ O_PRE_PL_3, O_PRE_PL_3, O_H_EXPANDING_WALL, O_H_EXPANDING_WALL,
37   /* 2c */ O_UNKNOWN, O_UNKNOWN, O_UNKNOWN, O_UNKNOWN,
38   /* 30 */ O_BUTTER_4, O_BUTTER_1, O_BUTTER_2, O_BUTTER_3,
39   /* 34 */ O_BUTTER_4, O_BUTTER_1, O_BUTTER_2, O_BUTTER_3,
40   /* 38 */ O_PLAYER, O_PLAYER, O_AMOEBA, O_AMOEBA,
41   /* 3c */ O_VOODOO, O_INVIS_OUTBOX, O_SLIME, O_UNKNOWN
42 };
43
44 /* conversion table for imported plck caves. */
45 static const GdElement plck_import_nybble[] =
46 {
47   /*  0 */ O_STONE, O_DIAMOND, O_MAGIC_WALL, O_BRICK,
48   /*  4 */ O_STEEL, O_H_EXPANDING_WALL, O_VOODOO, O_DIRT,
49   /*  8 */ O_FIREFLY_1, O_BUTTER_4, O_AMOEBA, O_SLIME,
50   /* 12 */ O_PRE_INVIS_OUTBOX, O_PRE_OUTBOX, O_INBOX, O_SPACE
51 };
52
53 /* conversion table for imported 1stb caves. */
54 static const GdElement firstboulder_import_table[] =
55 {
56   /*  0 */ O_SPACE, O_DIRT, O_BRICK, O_MAGIC_WALL,
57   /*  4 */ O_PRE_OUTBOX, O_OUTBOX, O_PRE_INVIS_OUTBOX, O_INVIS_OUTBOX,
58   /*  8 */ O_FIREFLY_1, O_FIREFLY_2, O_FIREFLY_3, O_FIREFLY_4,
59   /*  c */ O_FIREFLY_1, O_FIREFLY_2, O_FIREFLY_3, O_FIREFLY_4,
60   /* 10 */ O_STONE, O_STONE, O_STONE_F, O_STONE_F,
61   /* 14 */ O_DIAMOND, O_DIAMOND, O_DIAMOND_F, O_DIAMOND_F,
62   /* 18 */ O_PRE_CLOCK_1, O_PRE_CLOCK_2, O_PRE_CLOCK_3, O_PRE_CLOCK_4,
63   /* 1c */ O_BITER_SWITCH, O_BITER_SWITCH, O_BLADDER_SPENDER, O_PRE_DIA_1,
64   /* 20 */ O_PRE_DIA_1, O_PRE_DIA_2, O_PRE_DIA_3, O_PRE_DIA_4,
65   /* 24 */ O_PRE_DIA_5, O_INBOX, O_PRE_PL_1, O_PRE_PL_2,
66   /* 28 */ O_PRE_PL_3, O_CLOCK, O_H_EXPANDING_WALL, O_H_EXPANDING_WALL,    /* CLOCK: not mentioned in marek's bd inside faq */
67   /* 2c */ O_CREATURE_SWITCH, O_CREATURE_SWITCH, O_EXPANDING_WALL_SWITCH, O_EXPANDING_WALL_SWITCH,
68   /* 30 */ O_BUTTER_3, O_BUTTER_4, O_BUTTER_1, O_BUTTER_2,
69   /* 34 */ O_BUTTER_3, O_BUTTER_4, O_BUTTER_1, O_BUTTER_2,
70   /* 38 */ O_STEEL, O_SLIME, O_BOMB, O_SWEET,
71   /* 3c */ O_PRE_STONE_1, O_PRE_STONE_2, O_PRE_STONE_3, O_PRE_STONE_4,
72   /* 40 */ O_BLADDER, O_BLADDER_1, O_BLADDER_2, O_BLADDER_3,
73   /* 44 */ O_BLADDER_4, O_BLADDER_5, O_BLADDER_6, O_BLADDER_7,
74   /* 48 */ O_BLADDER_8, O_BLADDER_8, O_EXPLODE_1, O_EXPLODE_1,
75   /* 4c */ O_EXPLODE_2, O_EXPLODE_3, O_EXPLODE_4, O_EXPLODE_5,
76   /* 50 */ O_PLAYER, O_PLAYER, O_PLAYER_BOMB, O_PLAYER_BOMB,
77   /* 54 */ O_PLAYER_GLUED, O_PLAYER_GLUED, O_VOODOO, O_AMOEBA,
78   /* 58 */ O_AMOEBA, O_BOMB_TICK_1, O_BOMB_TICK_2, O_BOMB_TICK_3,
79   /* 5c */ O_BOMB_TICK_4, O_BOMB_TICK_5, O_BOMB_TICK_6, O_BOMB_TICK_7,
80   /* 60 */ O_BOMB_EXPL_1, O_BOMB_EXPL_2, O_BOMB_EXPL_3, O_BOMB_EXPL_4,
81   /* 64 */ O_GHOST, O_GHOST, O_GHOST_EXPL_1, O_GHOST_EXPL_2,
82   /* 68 */ O_GHOST_EXPL_3, O_GHOST_EXPL_4, O_GRAVESTONE, O_STONE_GLUED,
83   /* 6c */ O_DIAMOND_GLUED, O_DIAMOND_KEY, O_TRAPPED_DIAMOND, O_GRAVESTONE,
84   /* 70 */ O_WAITING_STONE, O_WAITING_STONE, O_CHASING_STONE, O_CHASING_STONE,
85   /* 74 */ O_PRE_STEEL_1, O_PRE_STEEL_2, O_PRE_STEEL_3, O_PRE_STEEL_4,
86   /* 78 */ O_BITER_1, O_BITER_2, O_BITER_3, O_BITER_4,
87   /* 7c */ O_BITER_1, O_BITER_2, O_BITER_3, O_BITER_4,
88 };
89
90 /* conversion table for imported crazy dream caves. */
91 static const GdElement crazydream_import_table[] =
92 {
93   /*  0 */ O_SPACE, O_DIRT, O_BRICK, O_MAGIC_WALL,
94   /*  4 */ O_PRE_OUTBOX, O_OUTBOX, O_PRE_INVIS_OUTBOX, O_INVIS_OUTBOX,
95   /*  8 */ O_FIREFLY_1, O_FIREFLY_2, O_FIREFLY_3, O_FIREFLY_4,
96   /*  c */ O_FIREFLY_1, O_FIREFLY_2, O_FIREFLY_3, O_FIREFLY_4,
97   /* 10 */ O_STONE, O_STONE, O_STONE_F, O_STONE_F,
98   /* 14 */ O_DIAMOND, O_DIAMOND, O_DIAMOND_F, O_DIAMOND_F,
99   /* 18 */ O_PRE_CLOCK_1, O_PRE_CLOCK_2, O_PRE_CLOCK_3, O_PRE_CLOCK_4,
100   /* 1c */ O_BITER_SWITCH, O_BITER_SWITCH, O_BLADDER_SPENDER, O_PRE_DIA_1,    /* 6 different stages */
101   /* 20 */ O_PRE_DIA_1, O_PRE_DIA_2, O_PRE_DIA_3, O_PRE_DIA_4,
102   /* 24 */ O_PRE_DIA_5, O_INBOX, O_PRE_PL_1, O_PRE_PL_2,
103   /* 28 */ O_PRE_PL_3, O_CLOCK, O_H_EXPANDING_WALL, O_H_EXPANDING_WALL,    /* CLOCK: not mentioned in marek's bd inside faq */
104   /* 2c */ O_CREATURE_SWITCH, O_CREATURE_SWITCH, O_EXPANDING_WALL_SWITCH, O_EXPANDING_WALL_SWITCH,
105   /* 30 */ O_BUTTER_3, O_BUTTER_4, O_BUTTER_1, O_BUTTER_2,
106   /* 34 */ O_BUTTER_3, O_BUTTER_4, O_BUTTER_1, O_BUTTER_2,
107   /* 38 */ O_STEEL, O_SLIME, O_BOMB, O_SWEET,
108   /* 3c */ O_PRE_STONE_1, O_PRE_STONE_2, O_PRE_STONE_3, O_PRE_STONE_4,
109   /* 40 */ O_BLADDER, O_BLADDER_1, O_BLADDER_2, O_BLADDER_3,
110   /* 44 */ O_BLADDER_4, O_BLADDER_5, O_BLADDER_6, O_BLADDER_7,
111   /* 48 */ O_BLADDER_8, O_BLADDER_8|SCANNED, O_EXPLODE_1, O_EXPLODE_1,
112   /* 4c */ O_EXPLODE_2, O_EXPLODE_3, O_EXPLODE_4, O_EXPLODE_5,
113   /* 50 */ O_PLAYER, O_PLAYER, O_PLAYER_BOMB, O_PLAYER_BOMB,
114   /* 54 */ O_PLAYER_GLUED, O_PLAYER_GLUED, O_VOODOO, O_AMOEBA,
115   /* 58 */ O_AMOEBA, O_BOMB_TICK_1, O_BOMB_TICK_2, O_BOMB_TICK_3,
116   /* 5c */ O_BOMB_TICK_4, O_BOMB_TICK_5, O_BOMB_TICK_6, O_BOMB_TICK_7,
117   /* 60 */ O_BOMB_EXPL_1, O_BOMB_EXPL_2, O_BOMB_EXPL_3, O_BOMB_EXPL_4,
118   /* 64 */ O_GHOST, O_GHOST, O_GHOST_EXPL_1, O_GHOST_EXPL_2,
119   /* 68 */ O_GHOST_EXPL_3, O_GHOST_EXPL_4, O_GRAVESTONE, O_STONE_GLUED,
120   /* 6c */ O_DIAMOND_GLUED, O_DIAMOND_KEY, O_TRAPPED_DIAMOND, O_GRAVESTONE,
121   /* 70 */ O_WAITING_STONE, O_WAITING_STONE, O_CHASING_STONE, O_CHASING_STONE,
122   /* 74 */ O_PRE_STEEL_1, O_PRE_STEEL_2, O_PRE_STEEL_3, O_PRE_STEEL_4,
123   /* 78 */ O_BITER_1, O_BITER_2, O_BITER_3, O_BITER_4,
124   /* 7c */ O_BITER_1, O_BITER_2, O_BITER_3, O_BITER_4,
125
126   /* 80 */ O_POT, O_PLAYER_STIRRING, O_GRAVITY_SWITCH, O_GRAVITY_SWITCH,
127   /* 84 */ O_PNEUMATIC_HAMMER, O_PNEUMATIC_HAMMER, O_BOX, O_BOX,
128   /* 88 */ O_UNKNOWN, O_UNKNOWN, O_ACID, O_ACID,
129   /* 8c */ O_KEY_1, O_KEY_2, O_KEY_3, O_UNKNOWN,
130   /* 90 */ O_UNKNOWN, O_UNKNOWN, O_UNKNOWN, O_UNKNOWN,
131   /* 94 */ O_UNKNOWN, O_TELEPORTER, O_UNKNOWN, O_SKELETON,
132   /* 98 */ O_WATER, O_WATER_16, O_WATER_15, O_WATER_14,
133   /* 9c */ O_WATER_13, O_WATER_12, O_WATER_11, O_WATER_10,
134   /* a0 */ O_WATER_9, O_WATER_8, O_WATER_7, O_WATER_6,
135   /* a4 */ O_WATER_5, O_WATER_4, O_WATER_3, O_WATER_2,
136   /* a8 */ O_WATER_1, O_COW_ENCLOSED_1, O_COW_ENCLOSED_2, O_COW_ENCLOSED_3,
137   /* ac */ O_COW_ENCLOSED_4, O_COW_ENCLOSED_5, O_COW_ENCLOSED_6, O_COW_ENCLOSED_7,
138   /* b0 */ O_COW_1, O_COW_2, O_COW_3, O_COW_4,
139   /* b4 */ O_COW_1, O_COW_2, O_COW_3, O_COW_4,
140   /* b8 */ O_DIRT_GLUED, O_STEEL_EXPLODABLE, O_DOOR_1, O_DOOR_2,
141   /* bc */ O_DOOR_3, O_FALLING_WALL, O_FALLING_WALL_F, O_FALLING_WALL_F,
142   /* c0 */ O_WALLED_DIAMOND, O_UNKNOWN, O_WALLED_KEY_1, O_WALLED_KEY_2,
143   /* c5 = brick?! (vital key), c7 = dirt?! (think twice) */
144   /* c7 = dirt, as it has a code which will change it to dirt. */
145   /* c4 */ O_WALLED_KEY_3, O_BRICK, O_UNKNOWN, O_DIRT,
146   /* c8 */ O_DIRT2, O_UNKNOWN, O_UNKNOWN, O_UNKNOWN,
147   /* cc */ O_UNKNOWN, O_UNKNOWN, O_UNKNOWN, O_UNKNOWN,
148   /* d0 */ O_UNKNOWN, O_UNKNOWN, O_UNKNOWN, O_UNKNOWN,
149   /* d4 */ O_UNKNOWN, O_UNKNOWN, O_UNKNOWN, O_UNKNOWN,
150   /* d8 */ O_UNKNOWN, O_UNKNOWN, O_UNKNOWN, O_UNKNOWN,
151   /* dc */ O_UNKNOWN, O_UNKNOWN, O_UNKNOWN, O_UNKNOWN,
152   /* e0 */ O_ALT_FIREFLY_1, O_ALT_FIREFLY_2, O_ALT_FIREFLY_3, O_ALT_FIREFLY_4,
153   /* e4 */ O_ALT_FIREFLY_1, O_ALT_FIREFLY_2, O_ALT_FIREFLY_3, O_ALT_FIREFLY_4,
154   /* e8 */ O_ALT_BUTTER_3, O_ALT_BUTTER_4, O_ALT_BUTTER_1, O_ALT_BUTTER_2,
155   /* ec */ O_ALT_BUTTER_3, O_ALT_BUTTER_4, O_ALT_BUTTER_1, O_ALT_BUTTER_2,
156   /* f0 */ O_WATER, O_WATER, O_WATER, O_WATER,
157   /* f4 */ O_WATER, O_WATER, O_WATER, O_WATER,
158   /* f8 */ O_WATER, O_WATER, O_WATER, O_WATER,
159   /* fc */ O_WATER, O_WATER, O_WATER, O_WATER,
160 };
161
162 /* conversion table for imported 1stb caves. */
163 const GdElement gd_crazylight_import_table[] =
164 {
165   /*  0 */ O_SPACE, O_DIRT, O_BRICK, O_MAGIC_WALL,
166   /*  4 */ O_PRE_OUTBOX, O_OUTBOX, O_PRE_INVIS_OUTBOX, O_INVIS_OUTBOX,
167   /*  8 */ O_FIREFLY_1, O_FIREFLY_2, O_FIREFLY_3, O_FIREFLY_4,
168   /*  c */ O_FIREFLY_1|SCANNED, O_FIREFLY_2|SCANNED, O_FIREFLY_3|SCANNED, O_FIREFLY_4|SCANNED,
169   /* 10 */ O_STONE, O_STONE|SCANNED, O_STONE_F, O_STONE_F|SCANNED,
170   /* 14 */ O_DIAMOND, O_DIAMOND|SCANNED, O_DIAMOND_F, O_DIAMOND_F|SCANNED,
171   /* 18 */ O_PRE_CLOCK_1, O_PRE_CLOCK_2, O_PRE_CLOCK_3, O_PRE_CLOCK_4,
172   /* 1c */ O_BITER_SWITCH, O_BITER_SWITCH, O_BLADDER_SPENDER, O_PRE_DIA_1,    /* 6 different stages, the first is the pre_dia_0 */
173   /* 20 */ O_PRE_DIA_1, O_PRE_DIA_2, O_PRE_DIA_3, O_PRE_DIA_4,
174   /* 24 */ O_PRE_DIA_5, O_INBOX, O_PRE_PL_1, O_PRE_PL_2,
175   /* 28 */ O_PRE_PL_3, O_CLOCK, O_H_EXPANDING_WALL, O_H_EXPANDING_WALL|SCANNED,    /* CLOCK: not mentioned in marek's bd inside faq */
176   /* 2c */ O_CREATURE_SWITCH, O_CREATURE_SWITCH, O_EXPANDING_WALL_SWITCH, O_EXPANDING_WALL_SWITCH,
177   /* 30 */ O_BUTTER_3, O_BUTTER_4, O_BUTTER_1, O_BUTTER_2,
178   /* 34 */ O_BUTTER_3|SCANNED, O_BUTTER_4|SCANNED, O_BUTTER_1|SCANNED, O_BUTTER_2|SCANNED,
179   /* 38 */ O_STEEL, O_SLIME, O_BOMB, O_SWEET,
180   /* 3c */ O_PRE_STONE_1, O_PRE_STONE_2, O_PRE_STONE_3, O_PRE_STONE_4,
181   /* 40 */ O_BLADDER, O_BLADDER_1, O_BLADDER_2, O_BLADDER_3,
182   /* 44 */ O_BLADDER_4, O_BLADDER_5, O_BLADDER_6, O_BLADDER_7,
183   /* 48 */ O_BLADDER_8, O_BLADDER_8|SCANNED, O_EXPLODE_1, O_EXPLODE_1,
184   /* 4c */ O_EXPLODE_2, O_EXPLODE_3, O_EXPLODE_4, O_EXPLODE_5,
185   /* 50 */ O_PLAYER, O_PLAYER|SCANNED, O_PLAYER_BOMB, O_PLAYER_BOMB|SCANNED,
186   /* 54 */ O_PLAYER_GLUED, O_PLAYER_GLUED|SCANNED, O_VOODOO, O_AMOEBA,
187   /* 58 */ O_AMOEBA|SCANNED, O_BOMB_TICK_1, O_BOMB_TICK_2, O_BOMB_TICK_3,
188   /* 5c */ O_BOMB_TICK_4, O_BOMB_TICK_5, O_BOMB_TICK_6, O_BOMB_TICK_7,
189   /* 60 */ O_BOMB_EXPL_1, O_BOMB_EXPL_2, O_BOMB_EXPL_3, O_BOMB_EXPL_4,
190   /* 64 */ O_ACID, O_ACID, O_FALLING_WALL, O_FALLING_WALL_F,
191   /* 68 */ O_FALLING_WALL_F|SCANNED, O_BOX, O_GRAVESTONE, O_STONE_GLUED,
192   /* 6c */ O_DIAMOND_GLUED, O_DIAMOND_KEY, O_TRAPPED_DIAMOND, O_GRAVESTONE,
193   /* 70 */ O_WAITING_STONE, O_WAITING_STONE|SCANNED, O_CHASING_STONE, O_CHASING_STONE|SCANNED,
194   /* 74 */ O_PRE_STEEL_1, O_PRE_STEEL_2, O_PRE_STEEL_3, O_PRE_STEEL_4,
195   /* 78 */ O_BITER_1, O_BITER_2, O_BITER_3, O_BITER_4,
196   /* 7c */ O_BITER_1|SCANNED, O_BITER_2|SCANNED, O_BITER_3|SCANNED, O_BITER_4|SCANNED,
197 };
198
199 GdPropertyDefault gd_defaults_bd1[] =
200 {
201   {CAVE_OFFSET(level_amoeba_threshold), 200},
202   {CAVE_OFFSET(amoeba_growth_prob), 31250},
203   {CAVE_OFFSET(amoeba_fast_growth_prob), 250000},
204   {CAVE_OFFSET(amoeba_timer_started_immediately), TRUE},
205   {CAVE_OFFSET(amoeba_timer_wait_for_hatching), FALSE},
206   {CAVE_OFFSET(lineshift), TRUE},
207   {CAVE_OFFSET(wraparound_objects), TRUE},
208   {CAVE_OFFSET(diagonal_movements), FALSE},
209   {CAVE_OFFSET(voodoo_collects_diamonds), FALSE},
210   {CAVE_OFFSET(voodoo_dies_by_stone), FALSE},
211   {CAVE_OFFSET(voodoo_disappear_in_explosion), TRUE},
212   {CAVE_OFFSET(voodoo_any_hurt_kills_player), FALSE},
213   {CAVE_OFFSET(creatures_backwards), FALSE},
214   {CAVE_OFFSET(creatures_direction_auto_change_on_start), FALSE},
215   {CAVE_OFFSET(creatures_direction_auto_change_time), 0},
216   {CAVE_OFFSET(level_hatching_delay_time[0]), 2},
217   {CAVE_OFFSET(intermission_instantlife), TRUE},
218   {CAVE_OFFSET(intermission_rewardlife), FALSE},
219   {CAVE_OFFSET(magic_wall_stops_amoeba), TRUE},
220   {CAVE_OFFSET(magic_timer_wait_for_hatching), FALSE},
221   {CAVE_OFFSET(pushing_stone_prob), 250000},
222   {CAVE_OFFSET(pushing_stone_prob_sweet), 1000000},
223   {CAVE_OFFSET(active_is_first_found), FALSE},
224   {CAVE_OFFSET(short_explosions), TRUE},
225   {CAVE_OFFSET(slime_predictable), TRUE},
226   {CAVE_OFFSET(snap_element), O_SPACE},
227   {CAVE_OFFSET(max_time), 999},
228
229   {CAVE_OFFSET(scheduling), GD_SCHEDULING_BD1},
230   {CAVE_OFFSET(pal_timing), TRUE},
231
232   {-1},
233 };
234
235 GdPropertyDefault gd_defaults_bd2[] =
236 {
237   {CAVE_OFFSET(level_amoeba_threshold), 200},
238   {CAVE_OFFSET(amoeba_growth_prob), 31250},
239   {CAVE_OFFSET(amoeba_fast_growth_prob), 250000},
240   {CAVE_OFFSET(amoeba_timer_started_immediately), FALSE},
241   {CAVE_OFFSET(amoeba_timer_wait_for_hatching), FALSE},
242   {CAVE_OFFSET(lineshift), TRUE},
243   {CAVE_OFFSET(wraparound_objects), TRUE},
244   {CAVE_OFFSET(diagonal_movements), FALSE},
245   {CAVE_OFFSET(voodoo_collects_diamonds), FALSE},
246   {CAVE_OFFSET(voodoo_dies_by_stone), FALSE},
247   {CAVE_OFFSET(voodoo_disappear_in_explosion), TRUE},
248   {CAVE_OFFSET(voodoo_any_hurt_kills_player), FALSE},
249   {CAVE_OFFSET(creatures_backwards), FALSE},
250   {CAVE_OFFSET(creatures_direction_auto_change_on_start), FALSE},
251   {CAVE_OFFSET(creatures_direction_auto_change_time), 0},
252   {CAVE_OFFSET(level_hatching_delay_time[0]), 2},
253   {CAVE_OFFSET(intermission_instantlife), TRUE},
254   {CAVE_OFFSET(intermission_rewardlife), FALSE},
255   {CAVE_OFFSET(magic_wall_stops_amoeba), FALSE},    /* marek roth bd inside faq 3.0 */
256   {CAVE_OFFSET(magic_timer_wait_for_hatching), FALSE},
257   {CAVE_OFFSET(pushing_stone_prob), 250000},
258   {CAVE_OFFSET(pushing_stone_prob_sweet), 1000000},
259   {CAVE_OFFSET(active_is_first_found), FALSE},
260   {CAVE_OFFSET(short_explosions), TRUE},
261   {CAVE_OFFSET(slime_predictable), TRUE},
262   {CAVE_OFFSET(snap_element), O_SPACE},
263   {CAVE_OFFSET(max_time), 999},
264
265   {CAVE_OFFSET(pal_timing), TRUE},
266   {CAVE_OFFSET(scheduling), GD_SCHEDULING_BD2},
267
268   {-1},
269 };
270
271 GdPropertyDefault gd_defaults_plck[] =
272 {
273   {CAVE_OFFSET(amoeba_growth_prob), 31250},
274   {CAVE_OFFSET(amoeba_fast_growth_prob), 250000},
275   {CAVE_OFFSET(amoeba_timer_started_immediately), FALSE},
276   {CAVE_OFFSET(amoeba_timer_wait_for_hatching), FALSE},
277   {CAVE_OFFSET(lineshift), TRUE},
278   {CAVE_OFFSET(wraparound_objects), TRUE},
279   {CAVE_OFFSET(border_scan_first_and_last), FALSE},
280   {CAVE_OFFSET(diagonal_movements), FALSE},
281   {CAVE_OFFSET(voodoo_collects_diamonds), FALSE},
282   {CAVE_OFFSET(voodoo_dies_by_stone), FALSE},
283   {CAVE_OFFSET(voodoo_disappear_in_explosion), TRUE},
284   {CAVE_OFFSET(voodoo_any_hurt_kills_player), FALSE},
285   {CAVE_OFFSET(creatures_backwards), FALSE},
286   {CAVE_OFFSET(creatures_direction_auto_change_on_start), FALSE},
287   {CAVE_OFFSET(creatures_direction_auto_change_time), 0},
288   {CAVE_OFFSET(level_hatching_delay_time[0]), 2},
289   {CAVE_OFFSET(intermission_instantlife), TRUE},
290   {CAVE_OFFSET(intermission_rewardlife), FALSE},
291   {CAVE_OFFSET(magic_wall_stops_amoeba), FALSE},
292   {CAVE_OFFSET(magic_timer_wait_for_hatching), FALSE},
293   {CAVE_OFFSET(pushing_stone_prob), 250000},
294   {CAVE_OFFSET(pushing_stone_prob_sweet), 1000000},
295   {CAVE_OFFSET(active_is_first_found), FALSE},
296   {CAVE_OFFSET(short_explosions), TRUE},
297   {CAVE_OFFSET(snap_element), O_SPACE},
298   {CAVE_OFFSET(max_time), 999},
299
300   {CAVE_OFFSET(pal_timing), TRUE},
301   {CAVE_OFFSET(scheduling), GD_SCHEDULING_PLCK},
302
303   {-1},
304 };
305
306 GdPropertyDefault gd_defaults_1stb[] =
307 {
308   {CAVE_OFFSET(amoeba_growth_prob), 31250},
309   {CAVE_OFFSET(amoeba_fast_growth_prob), 250000},
310   {CAVE_OFFSET(amoeba_timer_started_immediately), FALSE},
311   {CAVE_OFFSET(amoeba_timer_wait_for_hatching), TRUE},
312   {CAVE_OFFSET(lineshift), TRUE},
313   {CAVE_OFFSET(wraparound_objects), TRUE},
314   {CAVE_OFFSET(voodoo_collects_diamonds), TRUE},
315   {CAVE_OFFSET(voodoo_dies_by_stone), TRUE},
316   {CAVE_OFFSET(voodoo_disappear_in_explosion), FALSE},
317   {CAVE_OFFSET(voodoo_any_hurt_kills_player), FALSE},
318   {CAVE_OFFSET(creatures_direction_auto_change_on_start), TRUE},
319   {CAVE_OFFSET(level_hatching_delay_time[0]), 2},
320   {CAVE_OFFSET(intermission_instantlife), FALSE},
321   {CAVE_OFFSET(intermission_rewardlife), TRUE},
322   {CAVE_OFFSET(magic_timer_wait_for_hatching), TRUE},
323   {CAVE_OFFSET(pushing_stone_prob), 250000},
324   {CAVE_OFFSET(pushing_stone_prob_sweet), 1000000},
325   {CAVE_OFFSET(active_is_first_found), TRUE},
326   {CAVE_OFFSET(short_explosions), FALSE},
327   {CAVE_OFFSET(slime_predictable), TRUE},
328   {CAVE_OFFSET(snap_element), O_SPACE},
329   {CAVE_OFFSET(max_time), 999},
330
331   {CAVE_OFFSET(pal_timing), TRUE},
332   {CAVE_OFFSET(scheduling), GD_SCHEDULING_PLCK},
333   {CAVE_OFFSET(amoeba_enclosed_effect), O_PRE_DIA_1},    /* not immediately to diamond, but with animation */
334   {CAVE_OFFSET(dirt_looks_like), O_DIRT2},
335
336   {-1},
337 };
338
339 GdPropertyDefault gd_defaults_crdr_7[] =
340 {
341   {CAVE_OFFSET(amoeba_growth_prob), 31250},
342   {CAVE_OFFSET(amoeba_fast_growth_prob), 250000},
343   {CAVE_OFFSET(amoeba_timer_started_immediately), FALSE},
344   {CAVE_OFFSET(amoeba_timer_wait_for_hatching), TRUE},
345   {CAVE_OFFSET(lineshift), TRUE},
346   {CAVE_OFFSET(wraparound_objects), TRUE},
347   {CAVE_OFFSET(voodoo_collects_diamonds), TRUE},
348   {CAVE_OFFSET(voodoo_dies_by_stone), TRUE},
349   {CAVE_OFFSET(voodoo_disappear_in_explosion), FALSE},
350   {CAVE_OFFSET(voodoo_any_hurt_kills_player), FALSE},
351   {CAVE_OFFSET(creatures_direction_auto_change_on_start), FALSE},
352   {CAVE_OFFSET(level_hatching_delay_time[0]), 2},
353   {CAVE_OFFSET(intermission_instantlife), FALSE},
354   {CAVE_OFFSET(intermission_rewardlife), TRUE},
355   {CAVE_OFFSET(magic_timer_wait_for_hatching), TRUE},
356   {CAVE_OFFSET(pushing_stone_prob), 250000},
357   {CAVE_OFFSET(pushing_stone_prob_sweet), 1000000},
358   {CAVE_OFFSET(active_is_first_found), TRUE},
359   {CAVE_OFFSET(short_explosions), FALSE},
360   {CAVE_OFFSET(slime_predictable), TRUE},
361   {CAVE_OFFSET(snap_element), O_SPACE},
362   {CAVE_OFFSET(max_time), 999},
363
364   {CAVE_OFFSET(pal_timing), TRUE},
365   {CAVE_OFFSET(scheduling), GD_SCHEDULING_CRDR},
366   {CAVE_OFFSET(amoeba_enclosed_effect), O_PRE_DIA_1},    /* not immediately to diamond, but with animation */
367   {CAVE_OFFSET(water_does_not_flow_down), TRUE},
368   {CAVE_OFFSET(skeletons_worth_diamonds), 1},    /* in crdr, skeletons can also be used to open the gate */
369   {CAVE_OFFSET(gravity_affects_all), FALSE},    /* the intermission "survive" needs this flag */
370
371   {-1},
372 };
373
374 GdPropertyDefault gd_defaults_crli[] =
375 {
376   {CAVE_OFFSET(amoeba_growth_prob), 31250},
377   {CAVE_OFFSET(amoeba_fast_growth_prob), 250000},
378   {CAVE_OFFSET(amoeba_timer_started_immediately), FALSE},
379   {CAVE_OFFSET(amoeba_timer_wait_for_hatching), TRUE},
380   {CAVE_OFFSET(lineshift), TRUE},
381   {CAVE_OFFSET(wraparound_objects), TRUE},
382   {CAVE_OFFSET(voodoo_collects_diamonds), TRUE},
383   {CAVE_OFFSET(voodoo_dies_by_stone), TRUE},
384   {CAVE_OFFSET(voodoo_disappear_in_explosion), FALSE},
385   {CAVE_OFFSET(voodoo_any_hurt_kills_player), FALSE},
386   {CAVE_OFFSET(creatures_direction_auto_change_on_start), FALSE},
387   {CAVE_OFFSET(level_hatching_delay_time[0]), 2},
388   {CAVE_OFFSET(intermission_instantlife), FALSE},
389   {CAVE_OFFSET(intermission_rewardlife), TRUE},
390   {CAVE_OFFSET(magic_timer_wait_for_hatching), TRUE},
391   {CAVE_OFFSET(pushing_stone_prob), 250000},
392   {CAVE_OFFSET(pushing_stone_prob_sweet), 1000000},
393   {CAVE_OFFSET(active_is_first_found), TRUE},
394   {CAVE_OFFSET(short_explosions), FALSE},
395   {CAVE_OFFSET(slime_predictable), TRUE},
396   {CAVE_OFFSET(max_time), 999},
397
398   {CAVE_OFFSET(pal_timing), TRUE},
399   {CAVE_OFFSET(scheduling), GD_SCHEDULING_PLCK},
400   {CAVE_OFFSET(amoeba_enclosed_effect), O_PRE_DIA_1},    /* not immediately to diamond, but with animation */
401
402   {-1},
403 };
404
405 /* internal character (letter) codes in c64 games.
406    missing: "triple line" after >, diamond between ()s, player's head after )
407    used for converting names of caves imported from crli and other types of binary data */
408 const char gd_bd_internal_chars[] = "            ,!./0123456789:*<=>  ABCDEFGHIJKLMNOPQRSTUVWXYZ( ) _";
409
410 /* used for bdcff engine flag. */
411 const char *gd_engines[] =
412 {
413   "BD1",
414   "BD2",
415   "PLCK",
416   "1stB",
417   "CrDr",
418   "CrLi"
419 };
420
421 /* to convert predictable slime values to bit masks */
422 static int slime_shift_msb(int c64_data)
423 {
424   int i, perm;
425
426   perm = 0;
427
428   for (i = 0; i < c64_data; i++)
429     /* shift in this many msb 1's */
430     perm = (0x100|perm) >> 1;
431
432   return perm;
433 }
434
435 static GdElement bd1_import(byte c, int i)
436 {
437   if (c < ARRAY_SIZE(bd1_import_table))
438     return bd1_import_table[c];
439
440   Warn("Invalid BD1 element in imported file at cave data %d: %d", i, c);
441
442   return O_UNKNOWN;
443 }
444
445 /* deluxe caves 1 contained a special element, non-sloped brick. */
446 static GdElement deluxecaves_1_import(byte c, int i)
447 {
448   GdElement e = bd1_import(c, i);
449
450   if (e == O_H_EXPANDING_WALL)
451     e = O_BRICK_NON_SLOPED;
452
453   return e;
454 }
455
456 static GdElement firstboulder_import(byte c, int i)
457 {
458   if (c < ARRAY_SIZE(firstboulder_import_table))
459     return firstboulder_import_table[c];
460
461   Warn("Invalid 1stB element in imported file at cave data %d: %d", i, c);
462
463   return O_UNKNOWN;
464 }
465
466 static GdElement crazylight_import(byte c, int i)
467 {
468   if (c < ARRAY_SIZE(gd_crazylight_import_table))
469     return gd_crazylight_import_table[c] & O_MASK;    /* & O_MASK: do not import "scanned" flag */
470
471   Warn("Invalid CrLi element in imported file at cave data %d: %d", i, c);
472
473   return O_UNKNOWN;
474 }
475
476 GdPropertyDefault *gd_get_engine_default_array(GdEngine engine)
477 {
478   switch(engine)
479   {
480     case GD_ENGINE_BD1:
481       return gd_defaults_bd1;
482       break;
483
484     case GD_ENGINE_BD2:
485       return gd_defaults_bd2;
486       break;
487
488     case GD_ENGINE_PLCK:
489       return gd_defaults_plck;
490       break;
491
492     case GD_ENGINE_1STB:
493       return gd_defaults_1stb;
494       break;
495
496     case GD_ENGINE_CRDR7:
497       return gd_defaults_crdr_7;
498       break;
499
500     case GD_ENGINE_CRLI:
501       return gd_defaults_crli;
502       break;
503
504       /* to avoid compiler warning */
505     case GD_ENGINE_INVALID:
506       break;
507   }
508
509   return gd_defaults_bd1;
510 }
511
512 void gd_cave_set_engine_defaults(GdCave *cave, GdEngine engine)
513 {
514   gd_cave_set_defaults_from_array(cave, gd_get_engine_default_array(engine));
515
516   /* these have hardcoded ckdelay. */
517   /* setting this ckdelay array does not fit into the gd_struct_default scheme. */
518   if (engine == GD_ENGINE_BD1)
519   {
520     cave->level_ckdelay[0] = 12;
521     cave->level_ckdelay[1] = 6;
522     cave->level_ckdelay[2] = 3;
523     cave->level_ckdelay[3] = 1;
524     cave->level_ckdelay[4] = 0;
525   }
526
527   if (engine == GD_ENGINE_BD2)
528   {
529     cave->level_ckdelay[0] = 9;    /* 180ms */
530     cave->level_ckdelay[1] = 8;    /* 160ms */
531     cave->level_ckdelay[2] = 7;    /* 140ms */
532     cave->level_ckdelay[3] = 6;    /* 120ms */
533     cave->level_ckdelay[4] = 6;    /* 120ms (!) not faster than level4 */
534   }
535 }
536
537 GdEngine gd_cave_get_engine_from_string(const char *param)
538 {
539   int i;
540
541   for (i = 0; i < GD_ENGINE_INVALID; i++)
542     if (strcasecmp(param, gd_engines[i]) == 0)
543       return (GdEngine)i;
544
545   return GD_ENGINE_INVALID;
546 }
547
548 /****************************************************************************
549  *
550  * cave import routines.
551  * take a cave, data, and maybe remaining bytes.
552  * return the number of bytes read, -1 if error.
553  *
554  ****************************************************************************/
555
556 /*
557   take care of required diamonds values == 0 or > 100.
558   in original bd, the counter was only two-digit. so bd3 cave f
559   says 150 diamonds required, but you only had to collect 50.
560   also, gate opening is triggered by incrementing diamond
561   count and THEN checking if more required; so if required was
562   0, you had to collect 100. (also check crazy light 8 cave "1000")
563
564   http://www.boulder-dash.nl/forum/viewtopic.php?t=88
565 */
566
567 /* import bd1 cave data into our format. */
568 static int cave_copy_from_bd1(GdCave *cave, const byte *data, int remaining_bytes,
569                               GdCavefileFormat format)
570 {
571   int length, direction;
572   int index;
573   int level;
574   int x1, y1, x2, y2;
575   byte code;
576   GdElement elem;
577   GdElement (* import_func) (byte c, int i);
578   int i;
579
580   /* cant be shorted than this: header + no objects + delimiter */
581   if (remaining_bytes < 33)
582   {
583     Error("truncated BD1 cave data, %d bytes", remaining_bytes);
584
585     return -1;
586   }
587
588   gd_cave_set_engine_defaults(cave, GD_ENGINE_BD1);
589
590   if (format == GD_FORMAT_BD1_ATARI)
591     cave->scheduling = GD_SCHEDULING_BD1_ATARI;
592
593   if (format == GD_FORMAT_DC1)
594     import_func = deluxecaves_1_import;
595   else
596     import_func = bd1_import;
597
598   /* set visible size for intermission */
599   if (cave->intermission)
600   {
601     cave->x2 = 19;
602     cave->y2 = 11;
603   }
604
605   /* cave number data[0] */
606   cave->diamond_value = data[2];
607   cave->extra_diamond_value = data[3];
608
609   for (level = 0; level < 5; level++)
610   {
611     cave->level_amoeba_time[level] = data[1];
612
613     /* 0 immediately underflowed to 999, so we use 999. example: sendydash 3, cave 02. */
614     if (cave->level_amoeba_time[level] == 0)
615       cave->level_amoeba_time[level] = 999;
616
617     cave->level_magic_wall_time[level] = data[1];
618     cave->level_rand[level] = data[4 + level];
619     cave->level_diamonds[level] = data[9 + level] % 100;    /* check comment above */
620
621     /* gate opening is checked AFTER adding to diamonds collected, so 0 here means 100 to collect */
622     if (cave->level_diamonds[level] == 0)
623       cave->level_diamonds[level] = 100;
624     cave->level_time[level] = data[14 + level];
625   }
626
627   /* LogicDeLuxe extension: acid
628      $16 Acid speed (unused in the original BD1)
629      $17 Bit 2: if set, Acid's original position converts to explosion puff during spreading.
630      Otherwise, Acid remains intact, ie. it's just growing. (unused in the original BD1)
631      $1C Acid eats this element. (also Probability of element 1)
632
633      there is no problem importing these; as other bd1 caves did not contain acid at all,
634      so it does not matter how we set the values.
635   */
636
637   /* 0x1c index: same as probability1 !!!!! don't be surprised. we do a &0x3f because of this */
638   cave->acid_eats_this = import_func(data[0x1c] & 0x3F, 0x1c);
639
640   /* acid speed, *1e6 as probabilities are stored in int */
641   cave->acid_spread_ratio = data[0x16] / 255.0 * 1E6 + 0.5;
642
643   cave->acid_turns_to = (data[0x17] & (1 << 2)) ? O_EXPLODE_3 : O_ACID;
644
645   cave->colorb = GD_GDASH_BLACK;    /* border - black */
646   cave->color0 = GD_GDASH_BLACK;    /* background - black */
647   cave->color1= GD_GDASH_RED;
648   cave->color2 = GD_GDASH_PURPLE;
649   cave->color3 = GD_GDASH_YELLOW;
650   cave->color4 = cave->color3;    /* in bd1, amoeba was color3 */
651   cave->color5 = cave->color3;    /* no slime, but let it be color 3 */
652
653   /* random fill */
654   for (i = 0; i < 4; i++)
655   {
656     cave->random_fill[i] = import_func(data[24 + i], 24 + i);
657     cave->random_fill_probability[i] = data[28 + i];
658   }
659
660   /*
661    * Decode the explicit cave data
662    */
663   index = 32;
664
665   while (data[index] != 0xFF && index < remaining_bytes && index < 255)
666   {
667     code = data[index];
668
669     /* crazy dream 3 extension: */
670     if (code == 0x0f)
671     {
672       int x1, y1, nx, ny, dx, dy;
673       int x, y;
674
675       /* as this one uses nonstandard dx dy values, create points instead */
676       elem = import_func(data[index + 1], index + 1);
677       x1 = data[index + 2];
678       y1 = data[index + 3] - 2;
679       nx = data[index + 4];
680       ny = data[index + 5];
681       dx = data[index + 6];
682       dy = data[index + 7] + 1;
683
684       for (y = 0; y < ny; y++)
685       {
686         for (x = 0; x < nx; x++)
687         {
688           int pos = x1 + y1 * 40 + y * dy * 40 + x * dx;
689
690           cave->objects = list_append(cave->objects, gd_object_new_point(GD_OBJECT_LEVEL_ALL, pos % 40, pos / 40, elem));
691         }
692       }
693
694       index += 8;
695     }
696     else
697     {
698       /* object is code & 3f, object type is upper 2 bits */
699       elem = import_func(code & 0x3F, index);
700
701       switch ((code >> 6) & 3)
702       {
703         case 0:                /* 00: POINT */
704           x1 = data[index + 1];
705           y1 = data[index + 2] - 2;
706
707           if (x1 >= cave->w || y1 >= cave->h)
708             Warn("invalid point coordinates %d,%d at byte %d", x1, y1, index);
709
710           cave->objects = list_append(cave->objects, gd_object_new_point(GD_OBJECT_LEVEL_ALL, x1, y1, elem));
711
712           index += 3;
713           break;
714
715         case 1:                /* 01: LINE */
716           x1 = data[index + 1];
717           y1 = data[index + 2] - 2;
718           length = (byte)data[index + 3] - 1;
719           direction = data[index + 4];
720
721           if (length < 0)
722           {
723             Warn("line length negative, not displaying line at all, at byte %d", index);
724           }
725           else
726           {
727             if (direction > GD_MV_UP_LEFT)
728             {
729               Warn("invalid line direction %d at byte %d", direction, index);
730               direction = GD_MV_STILL;
731             }
732
733             x2 = x1 + length * gd_dx[direction + 1];
734             y2 = y1 + length * gd_dy[direction + 1];
735
736             if (x1 >= cave->w ||
737                 y1 >= cave->h ||
738                 x2 >= cave->w ||
739                 y2 >= cave->h)
740               Warn("invalid line coordinates %d,%d %d,%d at byte %d", x1, y1, x2, y2, index);
741
742             cave->objects = list_append(cave->objects, gd_object_new_line(GD_OBJECT_LEVEL_ALL, x1, y1, x2, y2, elem));
743           }
744
745           index += 5;
746           break;
747
748         case 2:                /* 10: FILLED RECTANGLE */
749           x1 = data[index + 1];
750           y1 = data[index + 2] - 2;
751           x2 = x1 + data[index + 3] - 1;    /* width */
752           y2 = y1 + data[index + 4] - 1;    /* height */
753
754           if (x1 >= cave->w ||
755               y1 >= cave->h ||
756               x2 >= cave->w ||
757               y2 >= cave->h)
758             Warn("invalid filled rectangle coordinates %d,%d %d,%d at byte %d", x1, y1, x2, y2, index);
759
760           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)));
761
762           index += 6;
763           break;
764
765         case 3:                /* 11: OPEN RECTANGLE (OUTLINE) */
766           x1 = data[index + 1];
767           y1 = data[index + 2] - 2;
768           x2 = x1 + data[index + 3] - 1;
769           y2 = y1 + data[index + 4] - 1;
770
771           if (x1 >= cave->w ||
772               y1 >= cave->h ||
773               x2 >= cave->w ||
774               y2 >= cave->h)
775             Warn("invalid rectangle coordinates %d,%d %d,%d at byte %d", x1, y1, x2, y2, index);
776
777           cave->objects = list_append(cave->objects, gd_object_new_rectangle(GD_OBJECT_LEVEL_ALL, x1, y1, x2, y2, elem));
778
779           index += 5;
780           break;
781       }
782     }
783   }
784
785   if (data[index] != 0xFF)
786   {
787     Error("import error, cave not delimited with 0xFF");
788     return -1;
789   }
790
791   return index + 1;
792 }
793
794 /* import bd2 cave data into our format. return number of bytes if pointer passed.
795    this is pretty much the same as above, only the encoding was different. */
796 static int cave_copy_from_bd2(GdCave *cave, const byte *data, int remaining_bytes,
797                               GdCavefileFormat format)
798 {
799   int index;
800   int i;
801   int x, y, rx, ry;
802   int x1, y1, x2, y2, dx, dy;
803   GdElement elem;
804
805   if (remaining_bytes < 0x1A + 5)
806   {
807     Error("truncated BD2 cave data, %d bytes", remaining_bytes);
808     return -1;
809   }
810
811   gd_cave_set_engine_defaults(cave, GD_ENGINE_BD2);
812
813   if (format == GD_FORMAT_BD2_ATARI)
814     cave->scheduling = GD_SCHEDULING_BD2_PLCK_ATARI;
815
816   /* set visible size for intermission */
817   if (cave->intermission)
818   {
819     cave->x2 = 19;
820     cave->y2 = 11;
821   }
822
823   cave->diamond_value = data[1];
824   cave->extra_diamond_value = data[2];
825
826   for (i = 0; i < 5; i++)
827   {
828     /* 0 immediately underflowed to 999, so we use 999. example: sendydash 3, cave 02. */
829     cave->level_amoeba_time[i] = data[0] == 0 ? 999 : data[0];
830     cave->level_rand[i] = data[13 + i];
831
832     /* gate opening is checked AFTER adding to diamonds collected, so 0 here is 1000 needed */
833     cave->level_diamonds[i] = data[8 + i] == 0 ? 1000 : data[8 + i];
834     cave->level_time[i] = data[3 + i];
835     cave->level_magic_wall_time[i] = data[0];
836   }
837
838   for (i = 0; i < 4; i++)
839   {
840     cave->random_fill[i] = bd1_import(data[0x16 + i], 0x16 + i);
841     cave->random_fill_probability[i] = data[0x12 + i];
842   }
843
844   /*
845    * Decode the explicit cave data
846    */
847   index = 0x1A;
848
849   while (data[index] != 0xFF && index < remaining_bytes)
850   {
851     int nx, ny;
852     unsigned int addr;
853     int val, n, bytes;
854     int length, direction;
855
856     switch (data[index])
857     {
858       case 0:                /* LINE */
859         elem = bd1_import(data[index + 1], index + 1);
860         y1 = data[index + 2];
861         x1 = data[index + 3];
862
863         /* they are multiplied by two - 0 is up, 2 is upright, 4 is right... */
864         direction = data[index + 4] / 2;
865         length = data[index + 5] - 1;
866
867         if (direction > GD_MV_UP_LEFT)
868         {
869           Warn("invalid line direction %d at byte %d", direction, index);
870           direction = GD_MV_STILL;
871         }
872
873         x2 = x1 + length * gd_dx[direction + 1];
874         y2 = y1 + length * gd_dy[direction + 1];
875
876         if (x1 >= cave->w ||
877             y1 >= cave->h ||
878             x2 >= cave->w ||
879             y2 >= cave->h)
880           Warn("invalid line coordinates %d,%d %d,%d at byte %d", x1, y1, x2, y2, index);
881
882         cave->objects = list_append(cave->objects, gd_object_new_line(GD_OBJECT_LEVEL_ALL, x1, y1, x2, y2, elem));
883
884         index += 6;
885         break;
886
887       case 1:                /* OPEN RECTANGLE */
888         elem = bd1_import(data[index + 1], index + 1);
889         y1 = data[index + 2];
890         x1 = data[index + 3];
891         y2 = y1 + data[index + 4] - 1;    /* height */
892         x2 = x1 + data[index + 5] - 1;
893
894         if (x1 >= cave->w ||
895             y1 >= cave->h ||
896             x2 >= cave->w ||
897             y2 >= cave->h)
898           Warn("invalid rectangle coordinates %d,%d %d,%d at byte %d", x1, y1, x2, y2, index);
899
900         cave->objects = list_append(cave->objects, gd_object_new_rectangle(GD_OBJECT_LEVEL_ALL, x1, y1, x2, y2, elem));
901
902         index += 6;
903         break;
904
905       case 2:                /* FILLED RECTANGLE */
906         elem = bd1_import(data[index + 1], index + 1);
907         y1 = data[index + 2];
908         x1 = data[index + 3];
909         y2 = y1 + data[index + 4] - 1;
910         x2 = x1 + data[index + 5] - 1;
911
912         if (x1 >= cave->w ||
913             y1 >= cave->h ||
914             x2 >= cave->w ||
915             y2 >= cave->h)
916           Warn("invalid filled rectangle coordinates %d,%d %d,%d at byte %d", x1, y1, x2, y2, index);
917
918         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)));
919
920         index += 7;
921         break;
922
923       case 3:                /* POINT */
924         elem = bd1_import(data[index + 1], index + 1);
925         y1 = data[index + 2];
926         x1 = data[index + 3];
927
928         if (x1 >= cave->w ||
929             y1 >= cave->h)
930           Warn("invalid point coordinates %d,%d at byte %d", x1, y1, index);
931
932         cave->objects = list_append(cave->objects, gd_object_new_point(GD_OBJECT_LEVEL_ALL, x1, y1, elem));
933
934         index += 4;
935         break;
936
937       case 4:                /* RASTER */
938         elem = bd1_import(data[index + 1], index + 1);
939         y1 = data[index + 2];   /* starting pos */
940         x1 = data[index + 3];
941         ny = data[index + 4] - 1; /* number of elements */
942         nx = data[index + 5] - 1;
943         dy = data[index + 6];   /* displacement */
944         dx = data[index + 7];
945         y2 = y1 + dy * ny;    /* calculate rectangle */
946         x2 = x1 + dx * nx;
947
948         /* guess this has to be here, after x2,y2 calculation, because of some bugs in imported data */
949         if (dy < 1)
950           dy = 1;
951         if (dx < 1)
952           dx = 1;
953
954         if (x1 >= cave->w ||
955             y1 >= cave->h ||
956             x2 >= cave->w ||
957             y2 >= cave->h)
958           Warn("invalid raster coordinates %d,%d %d,%d at byte %d", x1, y1, x2, y2, index);
959
960         cave->objects = list_append(cave->objects, gd_object_new_raster(GD_OBJECT_LEVEL_ALL, x1, y1, x2, y2, dx, dy, elem));
961
962         index += 8;
963         break;
964
965       case 5:
966         /* profi boulder extension: bitmap */
967         elem = bd1_import(data[index + 1], index + 1);
968         bytes = data[index + 2];    /* number of bytes in bitmap */
969
970         if (bytes >= cave->w * cave->h / 8)
971           Warn("invalid bitmap length at byte %d", index - 4);
972
973         addr = 0;
974         addr += data[index + 3];    /*msb */
975         addr += data[index + 4] << 8;    /*lsb */
976
977         /* this was a pointer to the cave work memory (used during game). */
978         addr -= 0x0850;
979
980         if (addr >= cave->w * cave->h)
981           Warn("invalid bitmap start address at byte %d", index - 4);
982
983         x1 = addr % 40;
984         y1 = addr / 40;
985
986         for (i = 0; i < bytes; i++)
987         {
988           /* for ("bytes" number of bytes) */
989           val = data[index + 5 + i];
990
991           for (n = 0; n < 8; n++)
992           {
993             /* for (8 bits in a byte) */
994             if ((val & 1) != 0) /* convert to single points... */
995               cave->objects = list_append(cave->objects, gd_object_new_point(GD_OBJECT_LEVEL_ALL, x1, y1, elem));
996
997             val >>= 1;
998             x1++;   /* next cave pos */
999
1000             if (x1 >= cave->w)
1001             {
1002               /* maybe next line in map */
1003               x1 = 0;
1004               y1++;
1005             }
1006           }
1007         }
1008
1009         index += 5 + bytes;    /* 5 description bytes and "bytes" data bytes */
1010         break;
1011
1012       case 6:                /* JOIN */
1013         dy = data[index + 3] / 40;
1014         dx = data[index + 3] % 40;    /* same byte!!! */
1015         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)));
1016
1017         index += 4;
1018         break;
1019
1020       case 7:             /* SLIME PERMEABILITY */
1021         /* interesting this is set here, and not in the cave header */
1022         for (i = 0; i < 5; i++)
1023           cave->level_slime_permeability_c64[i] = data[index + 1];
1024
1025         index += 2;
1026         break;
1027
1028       case 9:
1029         /* profi boulder extension by player: plck-like cave map. the import
1030            routine (any2gdash) inserts it here. */
1031         if (cave->map != NULL)
1032         {
1033           Error("contains more than one PLCK map");
1034           gd_cave_map_free(cave->map);
1035         }
1036
1037         cave->map = gd_cave_map_new(cave, GdElement);
1038
1039         for (x = 0; x < cave->w; x++)
1040         {
1041           /* fill the first and the last row with steel wall. */
1042           cave->map[0][x] = O_STEEL;
1043           cave->map[cave->h - 1][x] = O_STEEL;
1044         }
1045
1046         n = 0;    /* number of bytes read from map */
1047
1048         /* the first and the last rows are not stored. */
1049         for (y = 1; y < cave->h - 1; y++)
1050         {
1051           for (x = 0; x < cave->w; x += 2)
1052           {
1053             cave->map[y][x]     = plck_import_nybble[data[index + 3 + n] >> 4];    /* msb 4 bits */
1054             cave->map[y][x + 1] = plck_import_nybble[data[index + 3 + n] % 16];    /* lsb 4 bits */
1055             n++;
1056           }
1057         }
1058
1059         /* the position of inbox is stored. this is to check the cave */
1060         ry = data[index + 1] - 2;
1061         rx = data[index + 2];
1062
1063         /* at the start of the cave, bd scrolled to the last player placed during the drawing
1064            (setup) of the cave.
1065            i think this is why a map also stored the coordinates of the player - we can use
1066            this to check its integrity */
1067         if (rx >= cave->w || ry < 0 ||
1068             ry >= cave->h || cave->map[ry][rx] != O_INBOX)
1069           Warn ("embedded PLCK map may be corrupted, player coordinates %d,%d", rx, rx);
1070
1071         index += 3 + n;
1072         break;
1073
1074       default:
1075         Warn ("unknown bd2 extension no. %02x at byte %d", data[index], index);
1076
1077         index += 1;    /* skip that byte */
1078     }
1079   }
1080
1081   if (data[index] != 0xFF)
1082   {
1083     Error("import error, cave not delimited with 0xFF");
1084     return -1;
1085   }
1086
1087   /* skip delimiter */
1088   index++;
1089
1090   /* animation byte - told the engine which objects to animate - to make game faster */
1091   index++;
1092
1093   /* the colors from the memory dump are appended here by any2gdash */
1094   cave->colorb = GD_GDASH_BLACK;    /* border - black */
1095   cave->color0 = GD_GDASH_BLACK;    /* background - black */
1096   cave->color1 = GD_GDASH_RED;
1097   cave->color2 = GD_GDASH_PURPLE;
1098   cave->color3 = GD_GDASH_YELLOW;
1099   cave->color4 = cave->color3;    /* in bd1, amoeba was color3 */
1100   cave->color5 = cave->color3;    /* no slime, but let it be color 3 */
1101
1102   return index;
1103 }
1104
1105 /* import plck cave data into our format.
1106    length is always 512 bytes, and contains if it is an intermission cave. */
1107 static int cave_copy_from_plck(GdCave *cave, const byte *data,
1108                                int remaining_bytes, GdCavefileFormat format)
1109 {
1110   /* i don't really think that all this table is needed, but included to be complete. */
1111   /* this is for the dirt and expanding wall looks like effect. */
1112   /* it also contains the individual frames */
1113   static GdElement plck_graphic_table[] =
1114   {
1115     /* 3000 */ O_UNKNOWN, O_UNKNOWN, O_UNKNOWN, O_UNKNOWN, O_UNKNOWN, O_UNKNOWN, O_UNKNOWN, O_UNKNOWN,
1116     /* 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,
1117     /* 3200 */ O_AMOEBA, O_VOODOO, O_STONE, O_DIRT, O_DIAMOND, O_STEEL, O_PLAYER, O_BRICK,
1118     /* 3300 */ O_SPACE, O_OUTBOX_OPEN, O_FIREFLY_1, O_EXPLODE_1, O_EXPLODE_2, O_EXPLODE_3, O_MAGIC_WALL, O_MAGIC_WALL,
1119     /* 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,
1120     /* 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,
1121     /* 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,
1122     /* 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,
1123     /* 3800 */ O_AMOEBA, O_AMOEBA, O_AMOEBA, O_AMOEBA, O_AMOEBA, O_AMOEBA, O_AMOEBA, O_AMOEBA,
1124   };
1125
1126   int i;
1127   int x, y;
1128
1129   if (remaining_bytes < 512)
1130   {
1131     Error("truncated plck cave data!");
1132     return -1;
1133   }
1134
1135   gd_cave_set_engine_defaults(cave, GD_ENGINE_PLCK);
1136
1137   if (format == GD_FORMAT_PLC_ATARI)
1138     cave->scheduling = GD_SCHEDULING_BD2_PLCK_ATARI;
1139
1140   cave->intermission = data[0x1da] != 0;
1141
1142   if (cave->intermission)
1143   {
1144     /* set visible size for intermission */
1145     cave->x2 = 19;
1146     cave->y2 = 11;
1147   }
1148
1149   /* cave selection table, was not part of cave data, rather given in game packers.
1150    * if a new enough version of any2gdash is used, it will put information after the cave.
1151    * detect this here and act accordingly */
1152   if ((data[0x1f0] == data[0x1f1] - 1) &&
1153       (data[0x1f0] == 0x19 ||
1154        data[0x1f0] == 0x0e))
1155   {
1156     int j;
1157
1158     /* found selection table */
1159     cave->selectable = data[0x1f0] == 0x19;
1160     gd_strcpy(cave->name, "              ");
1161
1162     for (j = 0; j < 12; j++)
1163       cave->name[j] = data[0x1f2 + j];
1164
1165     chompString(cave->name);    /* remove spaces */
1166   }
1167   else
1168   {
1169     /* no selection info found, let intermissions be unselectable */
1170     cave->selectable = !cave->intermission;
1171   }
1172
1173   cave->diamond_value = data[0x1be];
1174   cave->extra_diamond_value = data[0x1c0];
1175
1176   for (i = 0; i < 5; i++)
1177   {
1178     /* plck doesnot really have levels, so just duplicate data five times */
1179     cave->level_amoeba_time[i] = data[0x1c4];
1180
1181     /* immediately underflowed to 999, so we use 999. example: sendydash 3, cave 02. */
1182     if (cave->level_amoeba_time[i] == 0)
1183       cave->level_amoeba_time[i] = 999;
1184
1185     cave->level_time[i] = data[0x1ba];
1186     cave->level_diamonds[i] = data[0x1bc];
1187
1188     /* gate opening is checked AFTER adding to diamonds collected, so 0 here is 1000 needed */
1189     if (cave->level_diamonds[i] == 0)
1190       cave->level_diamonds[i] = 1000;
1191
1192     cave->level_ckdelay[i] = data[0x1b8];
1193     cave->level_magic_wall_time[i] = data[0x1c6];
1194     cave->level_slime_permeability_c64[i] = slime_shift_msb(data[0x1c2]);
1195   }
1196
1197   cave->colorb = GD_GDASH_BLACK;    /* border - black */
1198   cave->color0 = GD_GDASH_BLACK;    /* background - black */
1199   cave->color1 = GD_GDASH_RED;
1200   cave->color2 = GD_GDASH_PURPLE;
1201   cave->color3 = GD_GDASH_YELLOW;
1202   cave->color4 = cave->color3;    /* in bd1, amoeba was color3 */
1203   cave->color5 = cave->color3;    /* no slime, but let it be color 3 */
1204
1205   /* ... the cave is stored like a map. */
1206   cave->map = gd_cave_map_new(cave, GdElement);
1207
1208   /* cave map looked like this. */
1209   /* two rows of steel wall ($44's), then cave description, 20 bytes (40 nybbles) for each line. */
1210   /* the bottom and top lines were not stored... originally. */
1211   /* some games write to the top line; so we import that, too. */
1212   /* also dlp 155 allowed writing to the bottom line; the first 20 $44-s now store the bottom line. */
1213   /* so the cave is essentially shifted one row down in the file: cave->map[y][x] = data[... y+1 mod height ][x] */
1214   for (y = 0; y < cave->h; y++)
1215   {
1216     for (x = 0; x < cave->w; x += 2)
1217     {
1218       /* msb 4 bits: we do not check index ranges, as >>4 and %16 will result in 0..15 */
1219       cave->map[y][x]     = plck_import_nybble[data[((y + 1) % cave->h) * 20 + x / 2] >> 4];
1220
1221       /* lsb 4 bits */
1222       cave->map[y][x + 1] = plck_import_nybble[data[((y + 1) % cave->h) * 20 + x / 2] % 16];
1223     }
1224   }
1225
1226   /* FOR NOW, WE DO NOT IMPORT THE BOTTOM BORDER */
1227   for (x = 0; x < cave->w; x++)
1228     cave->map[cave->h - 1][x] = O_STEEL;
1229
1230   /*
1231     if (steels && data[0] == 0x55)
1232     cave->map[cave->h - 1][0] = cave->map[cave->h - 1][1] = O_STEEL;
1233   */
1234
1235   /* check for diego-effects */
1236   /* c64 magic values (byte sequences)  0x20 0x90 0x46, also 0xa9 0x1c 0x85 */
1237   if ((data[0x1e5] == 0x20 &&
1238        data[0x1e6] == 0x90 &&
1239        data[0x1e7] == 0x46) ||
1240       (data[0x1e5] == 0xa9 &&
1241        data[0x1e6] == 0x1c &&
1242        data[0x1e7] == 0x85))
1243   {
1244     /* diego effects enabled. */
1245     cave->stone_bouncing_effect = bd1_import(data[0x1ea], 0x1ea);
1246     cave->diamond_falling_effect = bd1_import(data[0x1eb], 0x1eb);
1247
1248     /* explosions: 0x1e was explosion 5, if this is set to default, we also do not read it,
1249        as in our engine this would cause an O_EXPLODE_5 to stay there. */
1250     if (data[0x1ec] != 0x1e)
1251       cave->explosion_effect = bd1_import(data[0x1ec], 0x1ec);
1252
1253     /* pointer to element graphic.
1254        two bytes/column (one element), that is data[xxx] % 16 / 2.
1255        also there are 16bytes/row.
1256        that is, 0x44 = stone, upper left character. 0x45 = upper right,
1257        0x54 = lower right, 0x55 = lower right.
1258        so high nybble must be shifted right twice -> data[xxx]/16*4. */
1259     cave->dirt_looks_like           = plck_graphic_table[(data[0x1ed] / 16) * 4 + (data[0x1ed] % 16) / 2];
1260     cave->expanding_wall_looks_like = plck_graphic_table[(data[0x1ee] / 16) * 4 + (data[0x1ee] % 16) / 2];
1261
1262     for (i = 0; i < 5; i++)
1263       cave->level_amoeba_threshold[i] = data[0x1ef];
1264   }
1265
1266   return 512;
1267 }
1268
1269 /* no one's delight boulder dash essentially: rle compressed plck maps. */
1270 static int cave_copy_from_dlb(GdCave *cave, const byte *data, int remaining_bytes)
1271 {
1272   byte decomp[512];
1273   enum
1274   {
1275     START,        /* initial state */
1276     SEPARATOR,    /* got a separator */
1277     RLE,          /* after a separator, got the byte to duplicate */
1278     NORMAL        /* normal, copy bytes till separator */
1279   } state;
1280   int pos, cavepos, i, x, y;
1281   byte byte, separator;
1282
1283   gd_cave_set_engine_defaults(cave, GD_ENGINE_PLCK); /* essentially the plck engine */
1284
1285   for (i = 0; i < 5; i++)
1286   {
1287     /* does not really have levels, so just duplicate data five times */
1288     cave->level_time[i] = data[1];
1289     cave->level_diamonds[i] = data[2];
1290
1291     /* gate opening is checked AFTER adding to diamonds collected, so 0 here is 1000 needed */
1292     if (cave->level_diamonds[i] == 0)
1293       cave->level_diamonds[i] = 1000;
1294
1295     cave->level_ckdelay[i] = data[0];
1296     cave->level_amoeba_time[i] = data[6];
1297
1298     /* 0 immediately underflowed to 999, so we use 999. example: sendydash 3, cave 02. */
1299     if (cave->level_amoeba_time[i] == 0)
1300       cave->level_amoeba_time[i] = 999;
1301
1302     cave->level_magic_wall_time[i] = data[7];
1303     cave->level_slime_permeability_c64[i] = slime_shift_msb(data[5]);
1304   }
1305
1306   cave->diamond_value = data[3];
1307   cave->extra_diamond_value = data[4];
1308
1309   /* then 5 color bytes follow */
1310   cave->colorb = gd_c64_color(data[8]  & 0xf);    /* border */
1311   cave->color0 = gd_c64_color(data[9]  & 0xf);
1312   cave->color1 = gd_c64_color(data[10] & 0xf);
1313   cave->color2 = gd_c64_color(data[11] & 0xf);
1314   cave->color3 = gd_c64_color(data[12] & 0x7);     /* lower 3 bits only! */
1315   cave->color4 = cave->color3;    /* in plck, amoeba was color3 */
1316   cave->color5 = cave->color3;    /* same for slime */
1317
1318   /* cave map */
1319   pos = 13;    /* those 13 bytes were the cave values above */
1320   cavepos = 0;
1321   byte = 0;                    /* just to get rid of compiler warning */
1322   separator = 0;               /* just to get rid of compiler warning */
1323
1324   /* employ a state machine. */
1325   state = START;
1326
1327   while (cavepos < 400 && pos < remaining_bytes)
1328   {
1329     switch (state)
1330     {
1331       case START:
1332         /* first byte is a separator. remember it */
1333         separator = data[pos];
1334
1335         /* after the first separator, no rle data, just copy. */
1336         state = NORMAL;
1337         break;
1338
1339       case SEPARATOR:
1340         /* we had a separator. remember this byte, as this will be duplicated (or more) */
1341         byte = data[pos];
1342         state = RLE;
1343         break;
1344
1345       case RLE:
1346         /* we had the first byte, duplicate this n times. */
1347         if (data[pos] == 0xff)
1348         {
1349           /* if it is a 0xff, we will have another byte, which is also a length specifier. */
1350           /* and for this one, duplicate only 254 times */
1351           if (cavepos + 254 > 400)
1352           {
1353             Error("DLB import error: RLE data overflows buffer");
1354             return -1;
1355           }
1356
1357           for (i = 0; i < 254; i++)
1358             decomp[cavepos++] = byte;
1359         }
1360         else
1361         {
1362           /* if not 0xff, duplicate n times and back to copy mode */
1363           if (cavepos + data[pos] > 400)
1364           {
1365             Error("DLB import error: RLE data overflows buffer");
1366             return -1;
1367           }
1368
1369           for (i = 0; i < data[pos]; i++)
1370             decomp[cavepos++] = byte;
1371
1372           state = NORMAL;
1373         }
1374         break;
1375
1376       case NORMAL:
1377         /* bytes duplicated; now only copy the remaining, till the next separator. */
1378         if (data[pos] == separator)
1379           state = SEPARATOR;
1380         else
1381           decomp[cavepos++] = data[pos];    /* copy this byte and state is still NORMAL */
1382         break;
1383     }
1384
1385     pos++;
1386   }
1387
1388   if (cavepos != 400)
1389   {
1390     Error("DLB import error: RLE processing, cave length %d, should be 400", cavepos);
1391     return -1;
1392   }
1393
1394   /* process uncompressed map */
1395   cave->map = gd_cave_map_new(cave, GdElement);
1396
1397   for (x = 0; x < cave->w; x++)
1398   {
1399     /* fill the first and the last row with steel wall. */
1400     cave->map[0][x] = O_STEEL;
1401     cave->map[cave->h - 1][x] = O_STEEL;
1402   }
1403
1404   for (y = 1; y < cave->h - 1; y++)
1405   {
1406     for (x = 0; x < cave->w; x += 2)
1407     {
1408       /* msb 4 bits */
1409       cave->map[y][x]     = plck_import_nybble[decomp[((y - 1) * cave->w + x) / 2] >> 4];
1410       /* lsb 4 bits */
1411       cave->map[y][x + 1] = plck_import_nybble[decomp[((y - 1) * cave->w + x) / 2] % 16];
1412     }
1413   }
1414
1415   /* return number of bytes read from buffer */
1416   return pos;
1417 }
1418
1419 /* import plck cave data into our format. */
1420 static int cave_copy_from_1stb(GdCave *cave, const byte *data, int remaining_bytes)
1421 {
1422   int i;
1423   int x, y;
1424
1425   if (remaining_bytes < 1024)
1426   {
1427     Error("truncated 1stb cave data!");
1428
1429     return -1;
1430   }
1431
1432   gd_cave_set_engine_defaults(cave, GD_ENGINE_1STB);
1433
1434   /* copy name */
1435   gd_strcpy(cave->name, "              ");
1436
1437   for (i = 0; i < 14; i++)
1438   {
1439     int c = data[0x3a0 + i];
1440
1441     /* import cave name; a conversion table is used for each character */
1442     if (c < 0x40)
1443       c = gd_bd_internal_chars[c];
1444     else if (c == 0x74)
1445       c = ' ';
1446     else if (c == 0x76)
1447       c = '?';
1448     else
1449       c = ' ';    /* don't know this, so change to space */
1450
1451     if (i > 0)
1452       c = tolower(c);
1453
1454     cave->name[i] = c;
1455   }
1456
1457   chompString(cave->name);
1458
1459   cave->intermission = data[0x389] != 0;
1460
1461   /* if it is intermission but not scrollable */
1462   if (cave->intermission && !data[0x38c])
1463   {
1464     cave->x2 = 19;
1465     cave->y2 = 11;
1466   }
1467
1468   cave->diamond_value = 100 * data[0x379] + 10 * data[0x379 + 1] + data[0x379 + 2];
1469   cave->extra_diamond_value = 100 * data[0x376] + 10 * data[0x376 + 1] + data[0x376 + 2];
1470
1471   for (i = 0; i < 5; i++)
1472   {
1473     /* plck doesnot really have levels, so just duplicate data five times */
1474     cave->level_time[i] = 100 * data[0x370] + 10 * data[0x370+1] + data[0x370 + 2];
1475
1476     /* same as gate opening after 0 diamonds */
1477     if (cave->level_time[i] == 0)
1478       cave->level_time[i] = 1000;
1479
1480     cave->level_diamonds[i] = 100 * data[0x373] + 10 * data[0x373 + 1] + data[0x373 + 2];
1481
1482     /* gate opening is checked AFTER adding to diamonds collected, so 0 here is 1000 (!) needed */
1483     if (cave->level_diamonds[i] == 0)
1484       cave->level_diamonds[i] = 1000;
1485
1486     cave->level_ckdelay[i] = data[0x38a];
1487     cave->level_amoeba_time[i] = 256 * (int)data[0x37c] + data[0x37d];
1488
1489     /* 0 immediately underflowed to 999, so we use 999. example: sendydash 3, cave 02. */
1490     if (cave->level_amoeba_time[i] == 0)
1491       cave->level_amoeba_time[i] = 999;
1492
1493     cave->level_magic_wall_time[i] = 256 * (int)data[0x37e] + data[0x37f];
1494     cave->level_slime_permeability_c64[i] = data[0x38b];
1495     cave->level_bonus_time[i] = data[0x392];
1496     cave->level_penalty_time[i] = data[0x393];
1497     cave->level_amoeba_threshold[i] = 256 * (int)data[0x390] + data[0x390 + 1];
1498   }
1499
1500   /* also has no random data... */
1501   cave->colorb = gd_c64_color(data[0x384] & 0xf);    /* border */
1502   cave->color0 = gd_c64_color(data[0x385] & 0xf);
1503   cave->color1 = gd_c64_color(data[0x386] & 0xf);
1504   cave->color2 = gd_c64_color(data[0x387] & 0xf);
1505   cave->color3 = gd_c64_color(data[0x388] & 0x7);     /* lower 3 bits only! */
1506   cave->color4 = cave->color1;
1507   cave->color5 = cave->color1;
1508
1509   cave->amoeba_growth_prob = (4.0 * 1E6 / (data[0x382] + 1)) + 0.5;   /* probabilities store *1M */
1510   if (cave->amoeba_growth_prob > 1000000)
1511     cave->amoeba_growth_prob = 1000000;
1512
1513   cave->amoeba_fast_growth_prob = (4.0 * 1E6 / (data[0x383] + 1)) + 0.5;
1514   if (cave->amoeba_fast_growth_prob > 1000000)
1515     cave->amoeba_fast_growth_prob = 1000000;
1516
1517   if (data[0x380] != 0)
1518     cave->creatures_direction_auto_change_time = data[0x381];
1519   else
1520     cave->diagonal_movements = data[0x381] != 0;
1521
1522   /* ... the cave is stored like a map. */
1523   cave->map = gd_cave_map_new(cave, GdElement);
1524   for (y = 0; y < cave->h; y++)
1525     for (x = 0; x < cave->w; x++)
1526       cave->map[y][x] = firstboulder_import(data[y * 40 + x], y * 40 + x);
1527
1528   cave->magic_wall_sound = data[0x38d] == 0xf1;
1529
1530   /* 2d was a normal switch, 2e a changed one. */
1531   cave->creatures_backwards = data[0x38f] == 0x2d;
1532
1533   /* 2e horizontal, 2f vertical. */
1534   cave->expanding_wall_changed = data[0x38e] == 0x2f;
1535
1536   cave->biter_delay_frame       = data[0x394];
1537   cave->magic_wall_stops_amoeba = data[0x395] == 0;    /* negated!! */
1538
1539   cave->bomb_explosion_effect   = firstboulder_import(data[0x396], 0x396);
1540   cave->explosion_effect        = firstboulder_import(data[0x397], 0x397);
1541   cave->stone_bouncing_effect   = firstboulder_import(data[0x398], 0x398);
1542   cave->diamond_birth_effect    = firstboulder_import(data[0x399], 0x399);
1543   cave->magic_diamond_to        = firstboulder_import(data[0x39a], 0x39a);
1544
1545   cave->bladder_converts_by     = firstboulder_import(data[0x39b], 0x39b);
1546   cave->diamond_falling_effect  = firstboulder_import(data[0x39c], 0x39c);
1547   cave->biter_eat               = firstboulder_import(data[0x39d], 0x39d);
1548   cave->slime_eats_1            = firstboulder_import(data[0x39e], 0x39e);
1549   cave->slime_converts_1        = firstboulder_import(data[0x39e] + 3, 0x39e);
1550   cave->slime_eats_2            = firstboulder_import(data[0x39f], 0x39f);
1551   cave->slime_converts_2        = firstboulder_import(data[0x39f] + 3, 0x39f);
1552   cave->magic_diamond_to        = firstboulder_import(data[0x39a], 0x39a);
1553
1554   /* length is always 1024 bytes */
1555   return 1024;
1556 }
1557
1558 /* crazy dream 7 */
1559 static int cave_copy_from_crdr_7(GdCave *cave, const byte *data, int remaining_bytes)
1560 {
1561   int i, index;
1562   byte checksum;
1563
1564   /* if we have name, convert */
1565   gd_strcpy(cave->name, "              ");
1566
1567   for (i = 0; i < 14; i++)
1568   {
1569     int c = data[i];
1570
1571     /* import cave name; a conversion table is used for each character */
1572     if (c < 0x40)
1573       c = gd_bd_internal_chars[c];
1574     else if (c == 0x74)
1575       c = ' ';
1576     else if (c == 0x76)
1577       c = '?';
1578     else
1579       c = ' ';
1580     if (i > 0)
1581       c = tolower(c);
1582
1583     cave->name[i] = c;
1584   }
1585
1586   chompString(cave->name);    /* remove trailing and leading spaces */
1587
1588   cave->selectable = data[14] != 0;
1589
1590   /* jump 15 bytes, 14 was the name and 15 selectability */
1591   data += 15;
1592
1593   if (memcmp((char *)data + 0x30, "V4\0020", 4) != 0)
1594     Warn("unknown crdr version %c%c%c%c", data[0x30], data[0x31], data[0x32], data[0x33]);
1595
1596   gd_cave_set_engine_defaults(cave, GD_ENGINE_CRDR7);
1597
1598   for (i = 0; i < 5; i++)
1599   {
1600     cave->level_time[i] = (int)data[0x0] * 100 + data[0x1] * 10 + data[0x2];
1601
1602     /* same as gate opening after 0 diamonds */
1603     if (cave->level_time[i] == 0)
1604       cave->level_time[i] = 1000;
1605
1606     cave->level_diamonds[i] = (int)data[0x3] * 100 + data[0x4] * 10 + data[0x5];
1607
1608     /* gate opening is checked AFTER adding to diamonds collected, so 0 here is 1000 (!) needed */
1609     if (cave->level_diamonds[i] == 0)
1610       cave->level_diamonds[i] = 1000;
1611
1612     cave->level_ckdelay[i] = data[0x1A];
1613     cave->level_rand[i] = data[0x40];
1614     cave->level_amoeba_time[i] = (int)data[0xC] * 256 + data[0xD];
1615
1616     /* 0 immediately underflowed to 999, so we use 999. example: sendydash 3, cave 02. */
1617     if (cave->level_amoeba_time[i] == 0)
1618       cave->level_amoeba_time[i] = 999;
1619
1620     cave->level_magic_wall_time[i] = (int)data[0xE] * 256 + data[0xF];
1621     cave->level_slime_permeability_c64[i] = data[0x1B];
1622     cave->level_bonus_time[i] = data[0x22];
1623     cave->level_penalty_time[i] = data[0x23];
1624     cave->level_bonus_time[i] = data[0x22];
1625     cave->level_penalty_time[i] = data[0x23];
1626     cave->level_amoeba_threshold[i] = 256 * (int)data[0x20] + data[0x21];
1627   }
1628
1629   cave->extra_diamond_value = (int)data[0x6] * 100 + data[0x7] * 10 + data[0x8];
1630   cave->diamond_value       = (int)data[0x9] * 100 + data[0xA] * 10 + data[0xB];
1631
1632   if (data[0x10])
1633     cave->creatures_direction_auto_change_time = data[0x11];
1634
1635   cave->colorb = gd_c64_color(data[0x14] & 0xf);    /* border */
1636   cave->color0 = gd_c64_color(data[0x15] & 0xf);
1637   cave->color1 = gd_c64_color(data[0x16] & 0xf);
1638   cave->color2 = gd_c64_color(data[0x17] & 0xf);
1639   cave->color3 = gd_c64_color(data[0x18] & 0x7);     /* lower 3 bits only! */
1640   cave->color4 = cave->color3;
1641   cave->color5 = cave->color1;
1642   cave->intermission = data[0x19] != 0;
1643
1644   /* if it is intermission but not scrollable */
1645   if (cave->intermission && !data[0x1c])
1646   {
1647     cave->x2 = 19;
1648     cave->y2 = 11;
1649   }
1650
1651   /* AMOEBA in crazy dash 8:
1652      jsr $2500      ; generate true random
1653      and $94        ; binary and the current "probability"
1654      cmp #$04       ; compare to 4
1655      bcs out        ; jump out (do not expand) if carry set, ie. result was less than 4.
1656
1657      prob values can be like num = 3, 7, 15, 31, 63, ... n lsb bits count.
1658      0..3>=4?  0..7>=4?  0..15>=4? and similar.
1659      this way, probability of growing is 4/(num+1)
1660   */
1661
1662   cave->amoeba_growth_prob = (4.0 * 1E6 / (data[0x12] + 1)) + 0.5;   /* probabilities store * 1M */
1663   if (cave->amoeba_growth_prob > 1000000)
1664     cave->amoeba_growth_prob = 1000000;
1665
1666   cave->amoeba_fast_growth_prob = (4.0 * 1E6 / (data[0x13] + 1)) + 0.5;
1667   if (cave->amoeba_fast_growth_prob > 1000000)
1668     cave->amoeba_fast_growth_prob = 1000000;
1669
1670   /* expanding wall direction change - 2e horizontal, 2f vertical */
1671   cave->expanding_wall_changed = data[0x1e] == 0x2f;
1672
1673   /* 2c was a normal switch, 2d a changed one. */
1674   cave->creatures_backwards     = data[0x1f] == 0x2d;
1675   cave->biter_delay_frame       = data[0x24];
1676   cave->magic_wall_stops_amoeba = data[0x25] == 0;    /* negated!! */
1677
1678   cave->bomb_explosion_effect   = crazydream_import_table[data[0x26]];
1679   cave->explosion_effect        = crazydream_import_table[data[0x27]];
1680   cave->stone_bouncing_effect   = crazydream_import_table[data[0x28]];
1681   cave->diamond_birth_effect    = crazydream_import_table[data[0x29]];
1682   cave->magic_diamond_to        = crazydream_import_table[data[0x2a]];
1683
1684   cave->bladder_converts_by     = crazydream_import_table[data[0x2b]];
1685   cave->diamond_falling_effect  = crazydream_import_table[data[0x2c]];
1686   cave->biter_eat               = crazydream_import_table[data[0x2d]];
1687   cave->slime_eats_1            = crazydream_import_table[data[0x2e]];
1688   cave->slime_converts_1        = crazydream_import_table[data[0x2e] + 3];
1689   cave->slime_eats_2            = crazydream_import_table[data[0x2f]];
1690   cave->slime_converts_2        = crazydream_import_table[data[0x2f] + 3];
1691
1692   cave->diagonal_movements              = (data[0x34] & 1) != 0;
1693   cave->gravity_change_time             = data[0x35];
1694   cave->pneumatic_hammer_frame          = data[0x36];
1695   cave->hammered_wall_reappear_frame    = data[0x37];
1696   cave->hammered_walls_reappear         = data[0x3f] != 0;
1697
1698   /*
1699     acid in crazy dream 8:
1700     jsr $2500    ; true random
1701     cmp    $03a8    ; compare to ratio
1702     bcs out        ; if it was smaller, forget it for now.
1703
1704     ie. random<=ratio, then acid grows.
1705   */
1706
1707   /* 1e6, probabilities are stored as int */
1708   cave->acid_spread_ratio = data[0x38] / 255.0 * 1E6 + 0.5;
1709
1710   cave->acid_eats_this = crazydream_import_table[data[0x39]];
1711   switch(data[0x3a] & 3)
1712   {
1713     case 0: cave->gravity = GD_MV_UP; break;
1714     case 1: cave->gravity = GD_MV_DOWN; break;
1715     case 2: cave->gravity = GD_MV_LEFT; break;
1716     case 3: cave->gravity = GD_MV_RIGHT; break;
1717   }
1718
1719   cave->snap_element = ((data[0x3a] & 4) != 0) ? O_EXPLODE_1 : O_SPACE;
1720
1721   /* we do not know the values for these, so do not import */
1722   //    cave->dirt_looks_like... data[0x3c]
1723   //    cave->expanding_wall_looks_like... data[0x3b]
1724   for (i = 0; i < 4; i++)
1725   {
1726     cave->random_fill[i] = crazydream_import_table[data[0x41 + i]];
1727     cave->random_fill_probability[i] = data[0x45 + i];
1728   }
1729
1730   data += 0x49;
1731   index = 0;
1732
1733   while (data[index] != 0xff)
1734   {
1735     GdElement elem;
1736     int x1, y1, x2, y2, dx, dy;
1737     int nx, ny;
1738     int length, direction;
1739
1740     /* for copy&paste; copy&paste are different objects, static = ugly solution :) */
1741     static int cx1, cy1, cw, ch;
1742
1743     switch (data[index])
1744     {
1745       case 1:    /* point */
1746         elem = crazydream_import_table[data[index + 1]];
1747         x1 = data[index + 2];
1748         y1 = data[index + 3];
1749         if (x1 >= cave->w || y1 >= cave->h)
1750           Warn("invalid point coordinates %d,%d at byte %d", x1, y1, index);
1751
1752         cave->objects = list_append(cave->objects, gd_object_new_point(GD_OBJECT_LEVEL_ALL, x1, y1, elem));
1753
1754         index += 4;
1755         break;
1756
1757       case 2: /* rectangle */
1758         elem = crazydream_import_table[data[index + 1]];
1759         x1 = data[index + 2];
1760         y1 = data[index + 3];
1761         x2 = x1 + data[index + 4] - 1;
1762         y2 = y1 + data[index + 5] - 1;    /* height */
1763
1764         if (x1 >= cave->w ||
1765             y1 >= cave->h ||
1766             x2 >= cave->w ||
1767             y2 >= cave->h)
1768           Warn("invalid rectangle coordinates %d,%d %d,%d at byte %d", x1, y1, x2, y2, index);
1769
1770         cave->objects = list_append(cave->objects, gd_object_new_rectangle(GD_OBJECT_LEVEL_ALL, x1, y1, x2, y2, elem));
1771
1772         index += 6;
1773         break;
1774
1775       case 3: /* fillrect */
1776         x1 = data[index + 2];
1777         y1 = data[index + 3];
1778         x2 = x1 + data[index + 4] - 1;
1779         y2 = y1 + data[index + 5] - 1;
1780
1781         if (x1 >= cave->w ||
1782             y1 >= cave->h ||
1783             x2 >= cave->w ||
1784             y2 >= cave->h)
1785           Warn("invalid filled rectangle coordinates %d,%d %d,%d at byte %d", x1, y1, x2, y2, index);
1786
1787         /* border and inside of fill is the same element. */
1788         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]]));
1789
1790         index += 6;
1791         break;
1792
1793       case 4: /* line */
1794         elem = crazydream_import_table[data[index + 1]];
1795         if (elem == O_UNKNOWN)
1796           Warn("unknown element at %d: %x", index + 1, data[index + 1]);
1797
1798         x1 = data[index + 2];
1799         y1 = data[index + 3];
1800         length = data[index + 4];
1801         direction = data[index + 5];
1802         nx = ((signed)direction - 128) % 40;
1803         ny = ((signed)direction - 128) / 40;
1804         x2 = x1 + (length - 1) * nx;
1805         y2 = y1 + (length - 1) * ny;
1806
1807         /* if either is bigger than one, we cannot treat this as a line. create points instead */
1808         if (ABS(nx) >= 2 || ABS(ny) >= 2)
1809         {
1810           for (i = 0; i < length; i++)
1811           {
1812             cave->objects = list_append(cave->objects, gd_object_new_point(GD_OBJECT_LEVEL_ALL, x1, y1, elem));
1813             x1 += nx;
1814             y1 += ny;
1815           }
1816         }
1817         else
1818         {
1819           /* this is a normal line, and will be appended. only do the checking here */
1820           if (x1 >= cave->w ||
1821               y1 >= cave->h ||
1822               x2 >= cave->w ||
1823               y2 >= cave->h)
1824             Warn("invalid line coordinates %d,%d %d,%d at byte %d", x1, y1, x2, y2, index - 5);
1825
1826           cave->objects = list_append(cave->objects, gd_object_new_line(GD_OBJECT_LEVEL_ALL, x1, y1, x2, y2, elem));
1827         }
1828
1829         index += 6;
1830         break;
1831
1832       case 6: /* copy */
1833         cx1 = data[index + 1];
1834         cy1 = data[index + 2];
1835         cw = data[index + 3];
1836         ch = data[index + 4];
1837
1838         if (cx1 >= cave->w ||
1839             cy1 >= cave->h ||
1840             cx1 + cw > cave->w ||
1841             cy1 + ch > cave->h)
1842           Warn("invalid copy coordinates %d,%d or size %d,%d at byte %d", cx1, cy1, cw, ch, index);
1843
1844         index += 5;
1845         break;
1846
1847       case 7: /* paste */
1848         x1 = cx1;
1849         y1 = cy1;
1850
1851         /* original stored width and height, we store the coordinates of the source area */
1852         x2 = cx1 + cw - 1;
1853         y2 = cy1 + ch - 1;
1854         dx = data[index + 1];    /* new pos */
1855         dy = data[index + 2];
1856
1857         if (dx >= cave->w ||
1858             dy >= cave->h ||
1859             dx + cw > cave->w ||
1860             dy + ch > cave->h)
1861           Warn("invalid paste coordinates %d,%d at byte %d", dx, dy, index);
1862
1863         cave->objects = list_append(cave->objects, gd_object_new_copy_paste(GD_OBJECT_LEVEL_ALL, x1, y1, x2, y2, dx, dy, FALSE, FALSE));
1864
1865         index += 3;
1866         break;
1867
1868       case 11: /* raster */
1869         elem = crazydream_import_table[data[index + 1]];
1870         x1 = data[index + 2];
1871         y1 = data[index + 3];
1872         dx = data[index + 4];
1873         dy = data[index + 5];
1874         nx = data[index + 6] - 1;
1875         ny = data[index + 7] - 1;
1876         x2 = x1 + dx * nx;    /* calculate rectangle we use */
1877         y2 = y1 + dy * ny;
1878
1879         if (dx < 1)
1880           dx = 1;
1881         if (dy < 1)
1882           dy = 1;
1883
1884         if (x1 >= cave->w ||
1885             y1 >= cave->h ||
1886             x2 >= cave->w ||
1887             y2 >= cave->h)
1888           Warn("invalid raster coordinates %d,%d %d,%d at byte %d", x1, y1, x2, y2, index);
1889
1890         cave->objects = list_append(cave->objects, gd_object_new_raster(GD_OBJECT_LEVEL_ALL, x1, y1, x2, y2, dx, dy, elem));
1891
1892         index += 8;
1893         break;
1894
1895       default:
1896         Warn ("unknown crdr extension no. %02x at byte %d", data[index], index);
1897         index += 1;    /* skip that byte */
1898         break;
1899     }
1900   }
1901
1902   index++;    /* skip $ff */
1903
1904   /* crazy dream 7 hack */
1905   checksum = 0;
1906
1907   for (i = 0; i < 0x3b0; i++)
1908     checksum = checksum^data[i];
1909
1910   if (strEqual(cave->name, "Crazy maze") && checksum == 195)
1911     cave->skeletons_needed_for_pot = 0;
1912
1913   return 15 + 0x49 + index;
1914 }
1915
1916 static void crazy_dream_9_add_specials(GdCave *cave, const byte *buf, const int length)
1917 {
1918   byte checksum;
1919   int i;
1920
1921   /* crazy dream 9 hack */
1922   checksum = 0;
1923   for (i = 0; i < length; i++)
1924     checksum = checksum^buf[i];
1925
1926   /* check cave name and the checksum. both are hardcoded here */
1927   if (strEqual(cave->name, "Rockfall") && checksum == 134)
1928   {
1929     GdElement rand[4] = { O_DIAMOND, O_STONE, O_ACID, O_DIRT };
1930     int prob[4] = { 37, 32, 2, 0 };
1931     int seeds[5] = { -1, -1, -1, -1, -1 };
1932
1933     cave->objects = list_append(cave->objects, gd_object_new_random_fill(GD_OBJECT_LEVEL_ALL, 0, 0, 39, 21, seeds, O_DIRT, rand, prob, O_BLADDER_SPENDER, FALSE));
1934   }
1935
1936   if (strEqual(cave->name, "Roll dice now!") && checksum == 235)
1937   {
1938     GdElement rand[4] = { O_STONE, O_BUTTER_3, O_DIRT, O_DIRT };
1939     int prob[4] = { 0x18, 0x08, 0, 0 };
1940     int seeds[5] = { -1, -1, -1, -1, -1 };
1941
1942     cave->objects = list_append(cave->objects, gd_object_new_random_fill(GD_OBJECT_LEVEL_ALL, 0, 0, 39, 21, seeds, O_DIRT, rand, prob, O_BLADDER_SPENDER, FALSE));
1943   }
1944
1945   if (strEqual(cave->name, "Random maze") && checksum == 24)
1946   {
1947     int seeds[5] = { -1, -1, -1, -1, -1 };
1948     cave->objects = list_append(cave->objects, gd_object_new_maze(GD_OBJECT_LEVEL_ALL, 1, 4, 35, 20, 1, 1, O_NONE, O_DIRT, 50, seeds));
1949   }
1950
1951   if (strEqual(cave->name, "Metamorphosis") && checksum == 53)
1952   {
1953     int seeds[5] = { -1, -1, -1, -1, -1 };
1954     GdElement rand[4] = { O_STONE, O_DIRT, O_DIRT, O_DIRT };
1955     int prob[4] = { 0x18, 0, 0, 0 };
1956
1957     cave->objects = list_append(cave->objects, gd_object_new_maze(GD_OBJECT_LEVEL_ALL, 4, 1, 38, 19, 1, 3, O_NONE, O_BLADDER_SPENDER, 50, seeds));
1958     cave->objects = list_append(cave->objects, gd_object_new_random_fill(GD_OBJECT_LEVEL_ALL, 4, 1, 38, 19, seeds, O_DIRT, rand, prob, O_BLADDER_SPENDER, FALSE));
1959     cave->creatures_backwards = TRUE;    /* for some reason, this level worked like that */
1960   }
1961
1962   if (strEqual(cave->name, "All the way") && checksum == 33)
1963   {
1964     int seeds[5] = { -1, -1, -1, -1, -1 };
1965
1966     cave->objects = list_append(cave->objects, gd_object_new_maze_unicursal(GD_OBJECT_LEVEL_ALL, 1, 1, 35, 19, 1, 1, O_BRICK, O_PRE_DIA_1, 50, seeds));
1967
1968     /* a point which "breaks" the unicursal maze, making it one very long path */
1969     cave->objects = list_append(cave->objects, gd_object_new_point(GD_OBJECT_LEVEL_ALL, 35, 18, O_BRICK));
1970   }
1971 }
1972
1973 /* crazy light contruction kit */
1974 static int cave_copy_from_crli(GdCave *cave, const byte *data, int remaining_bytes)
1975 {
1976   byte uncompressed[1024];
1977   int datapos, cavepos, i, x, y;
1978   boolean cavefile;
1979   const char *versions[] = { "V2.2", "V2.6", "V3.0" };
1980   enum
1981   {
1982     none,
1983     V2_2,    /* XXX whats the difference between 2.2 and 2.6?*/
1984     V2_6,
1985     V3_0
1986   } version = none;
1987   GdElement (*import) (byte c, int i) = NULL;    /* import function */
1988
1989   gd_cave_set_engine_defaults(cave, GD_ENGINE_CRLI);
1990
1991   /* detect if this is a cavefile */
1992   if (data[0] == 0 &&
1993       data[1] == 0xc4 &&
1994       data[2] == 'D' &&
1995       data[3] == 'L' &&
1996       data[4] == 'P')
1997   {
1998     datapos = 5;    /* cavefile, skipping 0x00 0xc4 D L P */
1999     cavefile = TRUE;
2000   }
2001   else
2002   {
2003     /* converted from snapshot, skip "selectable" and 14byte name */
2004     datapos = 15;
2005     cavefile = FALSE;
2006   }
2007
2008   /* if we have name, convert */
2009   if (!cavefile)
2010   {
2011     gd_strcpy(cave->name, "              ");
2012
2013     for (i = 0; i < 14; i++)
2014     {
2015       int c = data[i + 1];
2016
2017       /* import cave name; a conversion table is used for each character */
2018       if (c < 0x40)
2019         c = gd_bd_internal_chars[c];
2020       else if (c == 0x74)
2021         c = ' ';
2022       else if (c == 0x76)
2023         c = '?';
2024       else
2025         c = ' ';
2026
2027       if (i > 0)
2028         c = tolower(c);
2029
2030       cave->name[i] = c;
2031     }
2032
2033     chompString(cave->name);    /* remove trailing and leading spaces */
2034   }
2035
2036   /* uncompress rle data */
2037   cavepos = 0;
2038
2039   while (cavepos < 0x3b0)
2040   {
2041     /* <- loop until the uncompressed reaches its size */
2042     if (datapos >= remaining_bytes)
2043     {
2044       Error("truncated crli cave data");
2045       return -1;
2046     }
2047
2048     if (data[datapos] == 0xbf)
2049     {
2050       /* magic value 0xbf is the escape byte */
2051       if (datapos + 2 >= remaining_bytes)
2052       {
2053         Error("truncated crli cave data");
2054         return -1;
2055       }
2056
2057       if (data[datapos + 2] + datapos >= sizeof(uncompressed))
2058       {
2059         /* we would run out of buffer, this must be some error */
2060         Error("invalid crli cave data - RLE length value is too big");
2061         return -1;
2062       }
2063
2064       /* 0xbf, number, byte to dup */
2065       for (i = 0; i < data[datapos + 2]; i++)
2066         uncompressed[cavepos++] = data[datapos + 1];
2067
2068       datapos += 3;
2069     }
2070     else
2071     {
2072       uncompressed[cavepos++] = data[datapos++];
2073     }
2074   }
2075
2076   /* check crli version */
2077   for (i = 0; i < ARRAY_SIZE(versions); i++)
2078     if (memcmp((char *)uncompressed + 0x3a0, versions[i], 4) == 0)
2079       version = i + 1;
2080
2081   /* v3.0 has falling wall and box, and no ghost. */
2082   import = version >= V3_0 ? crazylight_import : firstboulder_import;
2083
2084   if (version == none)
2085   {
2086     Warn("unknown crli version %c%c%c%c", uncompressed[0x3a0], uncompressed[0x3a1], uncompressed[0x3a2], uncompressed[0x3a3]);
2087     import = crazylight_import;
2088   }
2089
2090   /* process map */
2091   cave->map = gd_cave_map_new(cave, GdElement);
2092
2093   for (y = 0; y < cave->h; y++)
2094   {
2095     for (x = 0; x < cave->w; x++)
2096     {
2097       int index = y * cave->w + x;
2098
2099       cave->map[y][x] = import(uncompressed[index], index);
2100     }
2101   }
2102
2103   /* crli has no levels */
2104   for (i = 0; i < 5; i++)
2105   {
2106     cave->level_time[i] = (int)uncompressed[0x370] * 100 + uncompressed[0x371] * 10 + uncompressed[0x372];
2107
2108     /* same as gate opening after 0 diamonds */
2109     if (cave->level_time[i] == 0)
2110       cave->level_time[i] = 1000;
2111
2112     cave->level_diamonds[i] = (int)uncompressed[0x373] * 100 + uncompressed[0x374] * 10 + uncompressed[0x375];
2113
2114     /* gate opening is checked AFTER adding to diamonds collected, so 0 here is 1000 (!) needed */
2115     if (cave->level_diamonds[i] == 0)
2116       cave->level_diamonds[i] = 1000;
2117
2118     cave->level_ckdelay[i] = uncompressed[0x38A];
2119     cave->level_amoeba_time[i] = (int)uncompressed[0x37C] * 256 + uncompressed[0x37D];
2120
2121     /* 0 immediately underflowed to 999, so we use 999. example: sendydash 3, cave 02. */
2122     if (cave->level_amoeba_time[i] == 0)
2123       cave->level_amoeba_time[i] = 999;
2124
2125     cave->level_magic_wall_time[i] = (int)uncompressed[0x37E] * 256 + uncompressed[0x37F];
2126     cave->level_slime_permeability_c64[i] = uncompressed[0x38B];
2127     cave->level_bonus_time[i] = uncompressed[0x392];
2128     cave->level_penalty_time[i] = uncompressed[0x393];
2129     cave->level_amoeba_threshold[i] = 256 * (int)uncompressed[0x390] + uncompressed[0x390 + 1];
2130   }
2131
2132   cave->extra_diamond_value = (int)uncompressed[0x376] * 100 + uncompressed[0x377] * 10 + uncompressed[0x378];
2133   cave->diamond_value = (int)uncompressed[0x379] * 100 + uncompressed[0x37A] * 10 + uncompressed[0x37B];
2134
2135   if (uncompressed[0x380])
2136     cave->creatures_direction_auto_change_time = uncompressed[0x381];
2137
2138   cave->colorb = gd_c64_color(uncompressed[0x384] & 0xf);    /* border */
2139   cave->color0 = gd_c64_color(uncompressed[0x385] & 0xf);
2140   cave->color1 = gd_c64_color(uncompressed[0x386] & 0xf);
2141   cave->color2 = gd_c64_color(uncompressed[0x387] & 0xf);
2142   cave->color3 = gd_c64_color(uncompressed[0x388] & 0x7);    /* lower 3 bits only! */
2143   cave->color4 = cave->color3;
2144   cave->color5 = cave->color1;
2145   cave->intermission = uncompressed[0x389] != 0;
2146
2147   /* if it is intermission but not scrollable */
2148   if (cave->intermission && !uncompressed[0x38c])
2149   {
2150     cave->x2 = 19;
2151     cave->y2 = 11;
2152   }
2153
2154   /* AMOEBA in crazy dash 8:
2155      jsr $2500        ; generate true random
2156      and $94            ; binary and the current "probability"
2157      cmp #$04        ; compare to 4
2158      bcs out            ; jump out (do not expand) if carry set, ie. result was less than 4.
2159
2160      prob values can be like num = 3, 7, 15, 31, 63, ... n lsb bits count.
2161      0..3>=4?  0..7>=4?  0..15>=4? and similar.
2162      this way, probability of growing is 4/(num+1)
2163   */
2164
2165   /* probabilities store * 1M */
2166   cave->amoeba_growth_prob = (1E6 * 4.0 / (uncompressed[0x382] + 1)) + 0.5;
2167
2168   if (cave->amoeba_growth_prob > 1000000)
2169     cave->amoeba_growth_prob = 1000000;
2170
2171   cave->amoeba_fast_growth_prob = (1E6*4.0/(uncompressed[0x383] + 1)) + 0.5;
2172
2173   if (cave->amoeba_fast_growth_prob > 1000000)
2174     cave->amoeba_fast_growth_prob = 1000000;
2175
2176   /* 2c was a normal switch, 2d a changed one. */
2177   cave->creatures_backwards = uncompressed[0x38f] == 0x2d;
2178   cave->magic_wall_sound = uncompressed[0x38d] == 0xf1;
2179
2180   /* 2e horizontal, 2f vertical. we implement this by changing them */
2181   if (uncompressed[0x38e] == 0x2f)
2182   {
2183     for (y = 0; y < cave->h; y++)
2184     {
2185       for (x = 0; x < cave->w; x++)
2186       {
2187         if (cave->map[y][x] == O_H_EXPANDING_WALL)
2188           cave->map[y][x] = O_V_EXPANDING_WALL;
2189       }
2190     }
2191   }
2192
2193   cave->biter_delay_frame = uncompressed[0x394];
2194   cave->magic_wall_stops_amoeba = uncompressed[0x395] == 0;    /* negated!! */
2195   cave->bomb_explosion_effect = import(uncompressed[0x396], 0x396);
2196   cave->explosion_effect = import(uncompressed[0x397], 0x397);
2197   cave->stone_bouncing_effect = import(uncompressed[0x398], 0x398);
2198   cave->diamond_birth_effect = import(uncompressed[0x399], 0x399);
2199   cave->magic_diamond_to = import(uncompressed[0x39a], 0x39a);
2200
2201   cave->bladder_converts_by = import(uncompressed[0x39b], 0x39b);
2202   cave->diamond_falling_effect = import(uncompressed[0x39c], 0x39c);
2203   cave->biter_eat = import(uncompressed[0x39d], 0x39d);
2204   cave->slime_eats_1 = import(uncompressed[0x39e], 0x39e);
2205   cave->slime_converts_1 = import(uncompressed[0x39e] + 3, 0x39e);
2206   cave->slime_eats_2 = import(uncompressed[0x39f], 0x39f);
2207   cave->slime_converts_2 = import(uncompressed[0x39f] + 3, 0x39f);
2208
2209   /* v3.0 has some new properties. */
2210   if (version >= V3_0)
2211   {
2212     cave->diagonal_movements = uncompressed[0x3a4] != 0;
2213     cave->amoeba_too_big_effect = import(uncompressed[0x3a6], 0x3a6);
2214     cave->amoeba_enclosed_effect = import(uncompressed[0x3a7], 0x3a7);
2215
2216     /*
2217       acid in crazy dream 8:
2218       jsr $2500    ; true random
2219       cmp    $03a8    ; compare to ratio
2220       bcs out        ; if it was smaller, forget it for now.
2221
2222       ie. random<=ratio, then acid grows.
2223     */
2224
2225     /* * 1e6, probabilities are stored as int */
2226     cave->acid_spread_ratio = uncompressed[0x3a8] / 255.0 * 1E6;
2227     cave->acid_eats_this = import(uncompressed[0x3a9], 0x3a9);
2228     cave->expanding_wall_looks_like = import(uncompressed[0x3ab], 0x3ab);
2229     cave->dirt_looks_like = import(uncompressed[0x3ac], 0x3ac);
2230   }
2231   else
2232   {
2233     /* version is <= 3.0, so this is a 1stb cave. */
2234     /* the only parameters, for which this matters, are these: */
2235     if (uncompressed[0x380] != 0)
2236       cave->creatures_direction_auto_change_time = uncompressed[0x381];
2237     else
2238       cave->diagonal_movements = uncompressed[0x381] != 0;
2239   }
2240
2241   if (cavefile)
2242     cave->selectable = !cave->intermission;    /* best we can do */
2243   else
2244     cave->selectable = !data[0];    /* given by converter */
2245
2246   return datapos;
2247 }
2248
2249 GdCavefileFormat gd_caveset_imported_get_format(const byte *buf)
2250 {
2251   const char *s_bd1       = "GDashBD1";
2252   const char *s_bd1_atari = "GDashB1A";
2253   const char *s_dc1       = "GDashDC1";
2254   const char *s_bd2       = "GDashBD2";
2255   const char *s_bd2_atari = "GDashB2A";
2256   const char *s_plc       = "GDashPLC";
2257   const char *s_plc_atari = "GDashPCA";
2258   const char *s_dlb       = "GDashDLB";
2259   const char *s_crl       = "GDashCRL";
2260   const char *s_cd7       = "GDashCD7";
2261   const char *s_cd9       = "GDashCD9";
2262   const char *s_1st       = "GDash1ST";
2263
2264   if (memcmp((char *)buf, s_bd1, strlen(s_bd1)) == 0)
2265     return GD_FORMAT_BD1;
2266   if (memcmp((char *)buf, s_bd1_atari, strlen(s_bd1_atari)) == 0)
2267     return GD_FORMAT_BD1_ATARI;
2268   if (memcmp((char *)buf, s_dc1, strlen(s_dc1)) == 0)
2269     return GD_FORMAT_DC1;
2270   if (memcmp((char *)buf, s_bd2, strlen(s_bd2)) == 0)
2271     return GD_FORMAT_BD2;
2272   if (memcmp((char *)buf, s_bd2_atari, strlen(s_bd2_atari)) == 0)
2273     return GD_FORMAT_BD2_ATARI;
2274   if (memcmp((char *)buf, s_plc, strlen(s_plc)) == 0)
2275     return GD_FORMAT_PLC;
2276   if (memcmp((char *)buf, s_plc_atari, strlen(s_plc_atari)) == 0)
2277     return GD_FORMAT_PLC_ATARI;
2278   if (memcmp((char *)buf, s_dlb, strlen(s_dlb)) == 0)
2279     return GD_FORMAT_DLB;
2280   if (memcmp((char *)buf, s_crl, strlen(s_crl)) == 0)
2281     return GD_FORMAT_CRLI;
2282   if (memcmp((char *)buf, s_cd7, strlen(s_cd7)) == 0)
2283     return GD_FORMAT_CRDR_7;
2284   if (memcmp((char *)buf, s_cd9, strlen(s_cd9)) == 0)
2285     return GD_FORMAT_CRDR_9;
2286   if (memcmp((char *)buf, s_1st, strlen(s_1st)) == 0)
2287     return GD_FORMAT_FIRSTB;
2288
2289   return GD_FORMAT_UNKNOWN;
2290 }
2291
2292 /*
2293   Load caveset from memory buffer.
2294   Loads the caveset from a memory buffer.
2295   returns: List * of caves.
2296 */
2297 List *gd_caveset_import_from_buffer (const byte *buf, size_t length)
2298 {
2299   boolean numbering;
2300   int cavenum, intermissionnum, num;
2301   int cavelength, bufp;
2302   List *caveset = NULL, *iter;
2303   unsigned int encodedlength;
2304   GdCavefileFormat format;
2305
2306   if (length != -1 && length < 12)
2307   {
2308     Warn("buffer too short to be a GDash datafile");
2309     return NULL;
2310   }
2311
2312   encodedlength = (unsigned int)(*((unsigned int *)(buf + 8)));
2313   if (length != -1 && encodedlength != length - 12)
2314   {
2315     Warn("file length and data size mismatch in GDash datafile");
2316     return NULL;
2317   }
2318
2319   format = gd_caveset_imported_get_format(buf);
2320   if (format == GD_FORMAT_UNKNOWN)
2321   {
2322     Warn("buffer does not contain a GDash datafile");
2323     return NULL;
2324   }
2325
2326   buf += 12;
2327   length = encodedlength;
2328
2329   bufp = 0;
2330   cavenum = 0;
2331
2332   while (bufp < length)
2333   {
2334     GdCave *newcave;
2335     /* default is to append cave to caveset; list_insert appends when pos = -1 */
2336     int insertpos = -1;
2337
2338     newcave = gd_cave_new();
2339
2340     cavelength = 0;    /* to avoid compiler warning */
2341
2342     switch (format)
2343     {
2344       case GD_FORMAT_BD1:                /* boulder dash 1 */
2345       case GD_FORMAT_BD1_ATARI:          /* boulder dash 1, atari version */
2346       case GD_FORMAT_DC1:                /* deluxe caves 1 */
2347       case GD_FORMAT_BD2:                /* boulder dash 2 */
2348       case GD_FORMAT_BD2_ATARI:          /* boulder dash 2 */
2349         /* these are not in the data so we guess */
2350         newcave->selectable = (cavenum < 16) && (cavenum % 4 == 0);
2351         newcave->intermission = cavenum > 15;
2352
2353         /* no name, so we make up one */
2354         if (newcave->intermission)
2355           snprintf(newcave->name, sizeof(newcave->name), _("Intermission %d"), cavenum - 15);
2356         else
2357           snprintf(newcave->name, sizeof(newcave->name), _("Cave %c"), 'A' + cavenum);
2358
2359         switch(format)
2360         {
2361           case GD_FORMAT_BD1:
2362           case GD_FORMAT_BD1_ATARI:
2363           case GD_FORMAT_DC1:
2364             cavelength = cave_copy_from_bd1(newcave, buf + bufp, length - bufp, format);
2365             break;
2366           case GD_FORMAT_BD2:
2367           case GD_FORMAT_BD2_ATARI:
2368             cavelength = cave_copy_from_bd2(newcave, buf + bufp, length - bufp, format);
2369             break;
2370
2371           default:
2372             break;
2373         };
2374
2375         /* original bd1 had level order ABCDEFGH... and then the last four were the intermissions.
2376          * those should be inserted between D-E, H-I... caves. */
2377         if (cavenum > 15)
2378           insertpos = (cavenum - 15) * 5 - 1;
2379         break;
2380
2381       case GD_FORMAT_FIRSTB:
2382         cavelength = cave_copy_from_1stb(newcave, buf + bufp, length - bufp);
2383
2384         /* every fifth cave (4+1 intermission) is selectable. */
2385         newcave->selectable = cavenum % 5 == 0;
2386         break;
2387
2388       case GD_FORMAT_PLC:                /* peter liepa construction kit */
2389       case GD_FORMAT_PLC_ATARI:          /* peter liepa construction kit, atari version */
2390         cavelength = cave_copy_from_plck(newcave, buf + bufp, length - bufp, format);
2391         break;
2392
2393       case GD_FORMAT_DLB:
2394         /* no one's delight boulder dash, something like rle compressed plck caves */
2395         /* but there are 20 of them, as if it was a bd1 or bd2 game. also num%5 = 4 is intermission. */
2396         /* we have to set intermission flag on our own, as the file did not contain the info explicitly */
2397         newcave->intermission = (cavenum % 5) == 4;
2398         if (newcave->intermission)
2399         {
2400           /* also set visible size */
2401           newcave->x2 = 19;
2402           newcave->y2 = 11;
2403         }
2404
2405         newcave->selectable = cavenum % 5 == 0;    /* original selection scheme */
2406         if (newcave->intermission)
2407           snprintf(newcave->name, sizeof(newcave->name), _("Intermission %d"), cavenum / 5 + 1);
2408         else
2409           snprintf(newcave->name, sizeof(newcave->name), _("Cave %c"), 'A'+(cavenum % 5 + cavenum / 5 * 4));
2410
2411         cavelength = cave_copy_from_dlb (newcave, buf + bufp, length - bufp);
2412         break;
2413
2414       case GD_FORMAT_CRLI:
2415         cavelength = cave_copy_from_crli (newcave, buf + bufp, length - bufp);
2416         break;
2417
2418       case GD_FORMAT_CRDR_7:
2419         cavelength = cave_copy_from_crdr_7 (newcave, buf + bufp, length - bufp);
2420         break;
2421
2422       case GD_FORMAT_CRDR_9:
2423         cavelength = cave_copy_from_crli (newcave, buf + bufp, length - bufp);
2424         if (cavelength != -1)
2425           crazy_dream_9_add_specials(newcave, buf, cavelength);
2426         break;
2427
2428       case GD_FORMAT_UNKNOWN:
2429         break;
2430     }
2431
2432     if (cavelength == -1)
2433     {
2434       gd_cave_free(newcave);
2435
2436       Error("Aborting cave import.");
2437       break;
2438     }
2439     else
2440     {
2441       caveset = list_insert(caveset, newcave, insertpos);
2442     }
2443
2444     cavenum++;
2445     bufp += cavelength;
2446
2447     /* hack: some dlb files contain junk data after 20 caves. */
2448     if (format == GD_FORMAT_DLB && cavenum == 20)
2449     {
2450       if (bufp < length)
2451         Warn("excess data in dlb file, %d bytes", (int)(length-bufp));
2452       break;
2453     }
2454   }
2455
2456   /* try to detect if plc caves are in standard layout. */
2457   /* that is, caveset looks like an original, (4 cave,1 intermission)+ */
2458   if (format == GD_FORMAT_PLC)
2459     /* if no selection table stored by any2gdash */
2460     if ((buf[2 + 0x1f0] != buf[2 + 0x1f1] - 1) ||
2461         (buf[2 + 0x1f0] != 0x19 && buf[2 + 0x1f0] != 0x0e))
2462     {
2463       List *iter;
2464       int n;
2465       boolean standard;
2466
2467       standard = (list_length(caveset)%5) == 0;    /* cave count % 5 != 0 -> nonstandard */
2468
2469       for (n = 0, iter = caveset; iter != NULL; n++, iter = iter->next)
2470       {
2471         GdCave *cave = iter->data;
2472
2473         if ((n % 5 == 4 && !cave->intermission) ||
2474             (n % 5 != 4 && cave->intermission))
2475           standard = FALSE;    /* 4 cave, 1 intermission */
2476       }
2477
2478       /* if test passed, update selectability */
2479       if (standard)
2480         for (n = 0, iter = caveset; iter != NULL; n++, iter = iter->next)
2481         {
2482           GdCave *cave = iter->data;
2483
2484           /* update "selectable" */
2485           cave->selectable = (n % 5) == 0;
2486         }
2487     }
2488
2489   /* try to give some names for the caves */
2490   cavenum = 1;
2491   intermissionnum = 1;
2492   num = 1;
2493
2494   /* use numbering instead of letters, if following formats or too many caves
2495      (as we would run out of letters) */
2496   numbering = format == GD_FORMAT_PLC || format == GD_FORMAT_CRLI || list_length(caveset) > 26;
2497
2498   for (iter = caveset; iter != NULL; iter = iter->next)
2499   {
2500     GdCave *cave = (GdCave *)iter->data;
2501
2502     if (!strEqual(cave->name, ""))    /* if it already has a name, skip */
2503       continue;
2504
2505     if (cave->intermission)
2506     {
2507       /* intermission */
2508       if (numbering)
2509         snprintf(cave->name, sizeof(cave->name), _("Intermission %02d"), num);
2510       else
2511         snprintf(cave->name, sizeof(cave->name), _("Intermission %d"), intermissionnum);
2512     } else {
2513       if (numbering)
2514         snprintf(cave->name, sizeof(cave->name), _("Cave %02d"), num);
2515       else
2516         snprintf(cave->name, sizeof(cave->name), _("Cave %c"), 'A' - 1 + cavenum);
2517     }
2518
2519     num++;
2520     if (cave->intermission)
2521       intermissionnum++;
2522     else
2523       cavenum++;
2524   }
2525
2526   /* if the user requests, we make all caves selectable. intermissions not. */
2527   if (gd_import_as_all_caves_selectable)
2528   {
2529     for (iter = caveset; iter != NULL; iter = iter->next)
2530     {
2531       GdCave *cave = (GdCave *)iter->data;
2532
2533       /* make selectable if not an intermission. */
2534       /* also selectable, if it was selectable originally, for some reason. */
2535       cave->selectable = cave->selectable || !cave->intermission;
2536     }
2537   }
2538
2539   return caveset;
2540 }
2541
2542 /* to be called at program start. */
2543 void
2544 gd_c64_import_init_tables(void)
2545 {
2546 }