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