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