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