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