2 * Copyright (c) 2007, 2008, 2009, Czirkos Zoltan <cirix@fw.hu>
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.
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.
17 #include <glib/gi18n.h>
21 #include "caveobject.h"
25 #include "c64import.h"
27 /* conversion table for imported bd1 caves. */
28 static const GdElement bd1_import_table
[]={
29 /* 0 */ O_SPACE
, O_DIRT
, O_BRICK
, O_MAGIC_WALL
,
30 /* 4 */ O_PRE_OUTBOX
, O_OUTBOX
, O_STEEL_EXPLODABLE
, O_STEEL
,
31 /* 8 */ O_FIREFLY_1
, O_FIREFLY_2
, O_FIREFLY_3
, O_FIREFLY_4
,
32 /* c */ O_FIREFLY_1
, O_FIREFLY_2
, O_FIREFLY_3
, O_FIREFLY_4
,
33 /* 10 */ O_STONE
, O_STONE
, O_STONE_F
, O_STONE_F
,
34 /* 14 */ O_DIAMOND
, O_DIAMOND
, O_DIAMOND_F
, O_DIAMOND_F
,
35 /* 18 */ O_ACID
, O_ACID
, O_EXPLODE_1
, O_EXPLODE_2
, /* ACID: marek roth extension in crazy dream 3 */
36 /* 1c */ O_EXPLODE_3
, O_EXPLODE_4
, O_EXPLODE_5
, O_PRE_DIA_1
,
37 /* 20 */ O_PRE_DIA_2
, O_PRE_DIA_3
, O_PRE_DIA_4
, O_PRE_DIA_5
,
38 /* 24 */ O_PRE_DIA_5
, O_INBOX
, O_PRE_PL_1
, O_PRE_PL_2
,
39 /* 28 */ O_PRE_PL_3
, O_PRE_PL_3
, O_H_EXPANDING_WALL
, O_H_EXPANDING_WALL
,
40 /* 2c */ O_UNKNOWN
, O_UNKNOWN
, O_UNKNOWN
, O_UNKNOWN
,
41 /* 30 */ O_BUTTER_4
, O_BUTTER_1
, O_BUTTER_2
, O_BUTTER_3
,
42 /* 34 */ O_BUTTER_4
, O_BUTTER_1
, O_BUTTER_2
, O_BUTTER_3
,
43 /* 38 */ O_PLAYER
, O_PLAYER
, O_AMOEBA
, O_AMOEBA
,
44 /* 3c */ O_VOODOO
, O_INVIS_OUTBOX
, O_SLIME
, O_UNKNOWN
47 /* conversion table for imported plck caves. */
48 static const GdElement plck_import_nybble
[]={
49 /* 0 */ O_STONE
, O_DIAMOND
, O_MAGIC_WALL
, O_BRICK
,
50 /* 4 */ O_STEEL
, O_H_EXPANDING_WALL
, O_VOODOO
, O_DIRT
,
51 /* 8 */ O_FIREFLY_1
, O_BUTTER_4
, O_AMOEBA
, O_SLIME
,
52 /* 12 */ O_PRE_INVIS_OUTBOX
, O_PRE_OUTBOX
, O_INBOX
, O_SPACE
55 /* conversion table for imported 1stb caves. */
56 static const GdElement firstboulder_import_table
[]={
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 /* 28 */ O_PRE_PL_3
, O_CLOCK
, O_H_EXPANDING_WALL
, O_H_EXPANDING_WALL
, /* CLOCK: not mentioned in marek's bd inside faq */
68 /* 2c */ O_CREATURE_SWITCH
, O_CREATURE_SWITCH
, O_EXPANDING_WALL_SWITCH
, O_EXPANDING_WALL_SWITCH
,
69 /* 30 */ O_BUTTER_3
, O_BUTTER_4
, O_BUTTER_1
, O_BUTTER_2
,
70 /* 34 */ O_BUTTER_3
, O_BUTTER_4
, O_BUTTER_1
, O_BUTTER_2
,
71 /* 38 */ O_STEEL
, O_SLIME
, O_BOMB
, O_SWEET
,
72 /* 3c */ O_PRE_STONE_1
, O_PRE_STONE_2
, O_PRE_STONE_3
, O_PRE_STONE_4
,
73 /* 40 */ O_BLADDER
, O_BLADDER_1
, O_BLADDER_2
, O_BLADDER_3
,
74 /* 44 */ O_BLADDER_4
, O_BLADDER_5
, O_BLADDER_6
, O_BLADDER_7
,
75 /* 48 */ O_BLADDER_8
, O_BLADDER_8
, O_EXPLODE_1
, O_EXPLODE_1
,
76 /* 4c */ O_EXPLODE_2
, O_EXPLODE_3
, O_EXPLODE_4
, O_EXPLODE_5
,
77 /* 50 */ O_PLAYER
, O_PLAYER
, O_PLAYER_BOMB
, O_PLAYER_BOMB
,
78 /* 54 */ O_PLAYER_GLUED
, O_PLAYER_GLUED
, O_VOODOO
, O_AMOEBA
,
79 /* 58 */ O_AMOEBA
, O_BOMB_TICK_1
, O_BOMB_TICK_2
, O_BOMB_TICK_3
,
80 /* 5c */ O_BOMB_TICK_4
, O_BOMB_TICK_5
, O_BOMB_TICK_6
, O_BOMB_TICK_7
,
81 /* 60 */ O_BOMB_EXPL_1
, O_BOMB_EXPL_2
, O_BOMB_EXPL_3
, O_BOMB_EXPL_4
,
82 /* 64 */ O_GHOST
, O_GHOST
, O_GHOST_EXPL_1
, O_GHOST_EXPL_2
,
83 /* 68 */ O_GHOST_EXPL_3
, O_GHOST_EXPL_4
, O_GRAVESTONE
, O_STONE_GLUED
,
84 /* 6c */ O_DIAMOND_GLUED
, O_DIAMOND_KEY
, O_TRAPPED_DIAMOND
, O_GRAVESTONE
,
85 /* 70 */ O_WAITING_STONE
, O_WAITING_STONE
, O_CHASING_STONE
, O_CHASING_STONE
,
86 /* 74 */ O_PRE_STEEL_1
, O_PRE_STEEL_2
, O_PRE_STEEL_3
, O_PRE_STEEL_4
,
87 /* 78 */ O_BITER_1
, O_BITER_2
, O_BITER_3
, O_BITER_4
,
88 /* 7c */ O_BITER_1
, O_BITER_2
, O_BITER_3
, O_BITER_4
,
91 /* conversion table for imported crazy dream caves. */
92 static const GdElement crazydream_import_table
[]={
93 /* 0 */ O_SPACE
, O_DIRT
, O_BRICK
, O_MAGIC_WALL
,
94 /* 4 */ O_PRE_OUTBOX
, O_OUTBOX
, O_PRE_INVIS_OUTBOX
, O_INVIS_OUTBOX
,
95 /* 8 */ O_FIREFLY_1
, O_FIREFLY_2
, O_FIREFLY_3
, O_FIREFLY_4
,
96 /* c */ O_FIREFLY_1
, O_FIREFLY_2
, O_FIREFLY_3
, O_FIREFLY_4
,
97 /* 10 */ O_STONE
, O_STONE
, O_STONE_F
, O_STONE_F
,
98 /* 14 */ O_DIAMOND
, O_DIAMOND
, O_DIAMOND_F
, O_DIAMOND_F
,
99 /* 18 */ O_PRE_CLOCK_1
, O_PRE_CLOCK_2
, O_PRE_CLOCK_3
, O_PRE_CLOCK_4
,
100 /* 1c */ O_BITER_SWITCH
, O_BITER_SWITCH
, O_BLADDER_SPENDER
, O_PRE_DIA_1
, /* 6 different stages */
101 /* 20 */ O_PRE_DIA_1
, O_PRE_DIA_2
, O_PRE_DIA_3
, O_PRE_DIA_4
,
102 /* 24 */ O_PRE_DIA_5
, O_INBOX
, O_PRE_PL_1
, O_PRE_PL_2
,
103 /* 28 */ O_PRE_PL_3
, O_CLOCK
, O_H_EXPANDING_WALL
, O_H_EXPANDING_WALL
, /* CLOCK: not mentioned in marek's bd inside faq */
104 /* 2c */ O_CREATURE_SWITCH
, O_CREATURE_SWITCH
, O_EXPANDING_WALL_SWITCH
, O_EXPANDING_WALL_SWITCH
,
105 /* 30 */ O_BUTTER_3
, O_BUTTER_4
, O_BUTTER_1
, O_BUTTER_2
,
106 /* 34 */ O_BUTTER_3
, O_BUTTER_4
, O_BUTTER_1
, O_BUTTER_2
,
107 /* 38 */ O_STEEL
, O_SLIME
, O_BOMB
, O_SWEET
,
108 /* 3c */ O_PRE_STONE_1
, O_PRE_STONE_2
, O_PRE_STONE_3
, O_PRE_STONE_4
,
109 /* 40 */ O_BLADDER
, O_BLADDER_1
, O_BLADDER_2
, O_BLADDER_3
,
110 /* 44 */ O_BLADDER_4
, O_BLADDER_5
, O_BLADDER_6
, O_BLADDER_7
,
111 /* 48 */ O_BLADDER_8
, O_BLADDER_8
|SCANNED
, O_EXPLODE_1
, O_EXPLODE_1
,
112 /* 4c */ O_EXPLODE_2
, O_EXPLODE_3
, O_EXPLODE_4
, O_EXPLODE_5
,
113 /* 50 */ O_PLAYER
, O_PLAYER
, O_PLAYER_BOMB
, O_PLAYER_BOMB
,
114 /* 54 */ O_PLAYER_GLUED
, O_PLAYER_GLUED
, O_VOODOO
, O_AMOEBA
,
115 /* 58 */ O_AMOEBA
, O_BOMB_TICK_1
, O_BOMB_TICK_2
, O_BOMB_TICK_3
,
116 /* 5c */ O_BOMB_TICK_4
, O_BOMB_TICK_5
, O_BOMB_TICK_6
, O_BOMB_TICK_7
,
117 /* 60 */ O_BOMB_EXPL_1
, O_BOMB_EXPL_2
, O_BOMB_EXPL_3
, O_BOMB_EXPL_4
,
118 /* 64 */ O_GHOST
, O_GHOST
, O_GHOST_EXPL_1
, O_GHOST_EXPL_2
,
119 /* 68 */ O_GHOST_EXPL_3
, O_GHOST_EXPL_4
, O_GRAVESTONE
, O_STONE_GLUED
,
120 /* 6c */ O_DIAMOND_GLUED
, O_DIAMOND_KEY
, O_TRAPPED_DIAMOND
, O_GRAVESTONE
,
121 /* 70 */ O_WAITING_STONE
, O_WAITING_STONE
, O_CHASING_STONE
, O_CHASING_STONE
,
122 /* 74 */ O_PRE_STEEL_1
, O_PRE_STEEL_2
, O_PRE_STEEL_3
, O_PRE_STEEL_4
,
123 /* 78 */ O_BITER_1
, O_BITER_2
, O_BITER_3
, O_BITER_4
,
124 /* 7c */ O_BITER_1
, O_BITER_2
, O_BITER_3
, O_BITER_4
,
126 /* 80 */ O_POT
, O_PLAYER_STIRRING
, O_GRAVITY_SWITCH
, O_GRAVITY_SWITCH
,
127 /* 84 */ O_PNEUMATIC_HAMMER
, O_PNEUMATIC_HAMMER
, O_BOX
, O_BOX
,
128 /* 88 */ O_UNKNOWN
, O_UNKNOWN
, O_ACID
, O_ACID
,
129 /* 8c */ O_KEY_1
, O_KEY_2
, O_KEY_3
, O_UNKNOWN
,
130 /* 90 */ O_UNKNOWN
, O_UNKNOWN
, O_UNKNOWN
, O_UNKNOWN
,
131 /* 94 */ O_UNKNOWN
, O_TELEPORTER
, O_UNKNOWN
, O_SKELETON
,
132 /* 98 */ O_WATER
, O_WATER_16
, O_WATER_15
, O_WATER_14
,
133 /* 9c */ O_WATER_13
, O_WATER_12
, O_WATER_11
, O_WATER_10
,
134 /* a0 */ O_WATER_9
, O_WATER_8
, O_WATER_7
, O_WATER_6
,
135 /* a4 */ O_WATER_5
, O_WATER_4
, O_WATER_3
, O_WATER_2
,
136 /* a8 */ O_WATER_1
, O_COW_ENCLOSED_1
, O_COW_ENCLOSED_2
, O_COW_ENCLOSED_3
,
137 /* ac */ O_COW_ENCLOSED_4
, O_COW_ENCLOSED_5
, O_COW_ENCLOSED_6
, O_COW_ENCLOSED_7
,
138 /* b0 */ O_COW_1
, O_COW_2
, O_COW_3
, O_COW_4
,
139 /* b4 */ O_COW_1
, O_COW_2
, O_COW_3
, O_COW_4
,
140 /* b8 */ O_DIRT_GLUED
, O_STEEL_EXPLODABLE
, O_DOOR_1
, O_DOOR_2
,
141 /* bc */ O_DOOR_3
, O_FALLING_WALL
, O_FALLING_WALL_F
, O_FALLING_WALL_F
,
142 /* c0 */ O_WALLED_DIAMOND
, O_UNKNOWN
, O_WALLED_KEY_1
, O_WALLED_KEY_2
,
143 /* c5=brick?! (vital key), c7=dirt?! (think twice) */
144 /* c7=dirt, as it has a code which will change it to dirt. */
145 /* c4 */ O_WALLED_KEY_3
, O_BRICK
, O_UNKNOWN
, O_DIRT
,
146 /* c8 */ O_DIRT2
, O_UNKNOWN
, O_UNKNOWN
, O_UNKNOWN
,
147 /* cc */ O_UNKNOWN
, O_UNKNOWN
, O_UNKNOWN
, O_UNKNOWN
,
148 /* d0 */ O_UNKNOWN
, O_UNKNOWN
, O_UNKNOWN
, O_UNKNOWN
,
149 /* d4 */ O_UNKNOWN
, O_UNKNOWN
, O_UNKNOWN
, O_UNKNOWN
,
150 /* d8 */ O_UNKNOWN
, O_UNKNOWN
, O_UNKNOWN
, O_UNKNOWN
,
151 /* dc */ O_UNKNOWN
, O_UNKNOWN
, O_UNKNOWN
, O_UNKNOWN
,
152 /* e0 */ O_ALT_FIREFLY_1
, O_ALT_FIREFLY_2
, O_ALT_FIREFLY_3
, O_ALT_FIREFLY_4
,
153 /* e4 */ O_ALT_FIREFLY_1
, O_ALT_FIREFLY_2
, O_ALT_FIREFLY_3
, O_ALT_FIREFLY_4
,
154 /* e8 */ O_ALT_BUTTER_3
, O_ALT_BUTTER_4
, O_ALT_BUTTER_1
, O_ALT_BUTTER_2
,
155 /* ec */ O_ALT_BUTTER_3
, O_ALT_BUTTER_4
, O_ALT_BUTTER_1
, O_ALT_BUTTER_2
,
156 /* f0 */ O_WATER
, O_WATER
, O_WATER
, O_WATER
,
157 /* f4 */ O_WATER
, O_WATER
, O_WATER
, O_WATER
,
158 /* f8 */ O_WATER
, O_WATER
, O_WATER
, O_WATER
,
159 /* fc */ O_WATER
, O_WATER
, O_WATER
, O_WATER
,
162 /* conversion table for imported 1stb caves. */
163 const GdElement gd_crazylight_import_table
[]={
164 /* 0 */ O_SPACE
, O_DIRT
, O_BRICK
, O_MAGIC_WALL
,
165 /* 4 */ O_PRE_OUTBOX
, O_OUTBOX
, O_PRE_INVIS_OUTBOX
, O_INVIS_OUTBOX
,
166 /* 8 */ O_FIREFLY_1
, O_FIREFLY_2
, O_FIREFLY_3
, O_FIREFLY_4
,
167 /* c */ O_FIREFLY_1
|SCANNED
, O_FIREFLY_2
|SCANNED
, O_FIREFLY_3
|SCANNED
, O_FIREFLY_4
|SCANNED
,
168 /* 10 */ O_STONE
, O_STONE
|SCANNED
, O_STONE_F
, O_STONE_F
|SCANNED
,
169 /* 14 */ O_DIAMOND
, O_DIAMOND
|SCANNED
, O_DIAMOND_F
, O_DIAMOND_F
|SCANNED
,
170 /* 18 */ O_PRE_CLOCK_1
, O_PRE_CLOCK_2
, O_PRE_CLOCK_3
, O_PRE_CLOCK_4
,
171 /* 1c */ O_BITER_SWITCH
, O_BITER_SWITCH
, O_BLADDER_SPENDER
, O_PRE_DIA_1
, /* 6 different stages, the first is the pre_dia_0 */
172 /* 20 */ O_PRE_DIA_1
, O_PRE_DIA_2
, O_PRE_DIA_3
, O_PRE_DIA_4
,
173 /* 24 */ O_PRE_DIA_5
, O_INBOX
, O_PRE_PL_1
, O_PRE_PL_2
,
174 /* 28 */ O_PRE_PL_3
, O_CLOCK
, O_H_EXPANDING_WALL
, O_H_EXPANDING_WALL
|SCANNED
, /* CLOCK: not mentioned in marek's bd inside faq */
175 /* 2c */ O_CREATURE_SWITCH
, O_CREATURE_SWITCH
, O_EXPANDING_WALL_SWITCH
, O_EXPANDING_WALL_SWITCH
,
176 /* 30 */ O_BUTTER_3
, O_BUTTER_4
, O_BUTTER_1
, O_BUTTER_2
,
177 /* 34 */ O_BUTTER_3
|SCANNED
, O_BUTTER_4
|SCANNED
, O_BUTTER_1
|SCANNED
, O_BUTTER_2
|SCANNED
,
178 /* 38 */ O_STEEL
, O_SLIME
, O_BOMB
, O_SWEET
,
179 /* 3c */ O_PRE_STONE_1
, O_PRE_STONE_2
, O_PRE_STONE_3
, O_PRE_STONE_4
,
180 /* 40 */ O_BLADDER
, O_BLADDER_1
, O_BLADDER_2
, O_BLADDER_3
,
181 /* 44 */ O_BLADDER_4
, O_BLADDER_5
, O_BLADDER_6
, O_BLADDER_7
,
182 /* 48 */ O_BLADDER_8
, O_BLADDER_8
|SCANNED
, O_EXPLODE_1
, O_EXPLODE_1
,
183 /* 4c */ O_EXPLODE_2
, O_EXPLODE_3
, O_EXPLODE_4
, O_EXPLODE_5
,
184 /* 50 */ O_PLAYER
, O_PLAYER
|SCANNED
, O_PLAYER_BOMB
, O_PLAYER_BOMB
|SCANNED
,
185 /* 54 */ O_PLAYER_GLUED
, O_PLAYER_GLUED
|SCANNED
, O_VOODOO
, O_AMOEBA
,
186 /* 58 */ O_AMOEBA
|SCANNED
, O_BOMB_TICK_1
, O_BOMB_TICK_2
, O_BOMB_TICK_3
,
187 /* 5c */ O_BOMB_TICK_4
, O_BOMB_TICK_5
, O_BOMB_TICK_6
, O_BOMB_TICK_7
,
188 /* 60 */ O_BOMB_EXPL_1
, O_BOMB_EXPL_2
, O_BOMB_EXPL_3
, O_BOMB_EXPL_4
,
189 /* 64 */ O_ACID
, O_ACID
, O_FALLING_WALL
, O_FALLING_WALL_F
,
190 /* 68 */ O_FALLING_WALL_F
|SCANNED
, O_BOX
, O_GRAVESTONE
, O_STONE_GLUED
,
191 /* 6c */ O_DIAMOND_GLUED
, O_DIAMOND_KEY
, O_TRAPPED_DIAMOND
, O_GRAVESTONE
,
192 /* 70 */ O_WAITING_STONE
, O_WAITING_STONE
|SCANNED
, O_CHASING_STONE
, O_CHASING_STONE
|SCANNED
,
193 /* 74 */ O_PRE_STEEL_1
, O_PRE_STEEL_2
, O_PRE_STEEL_3
, O_PRE_STEEL_4
,
194 /* 78 */ O_BITER_1
, O_BITER_2
, O_BITER_3
, O_BITER_4
,
195 /* 7c */ O_BITER_1
|SCANNED
, O_BITER_2
|SCANNED
, O_BITER_3
|SCANNED
, O_BITER_4
|SCANNED
,
199 static guint8 no1_default_colors
[]={
200 4, 10, 1, 8, 9, 3, 12, 11, 1, 6, 14, 7, 14, 3, 7,
201 5, 8, 7, 4, 9, 3, 10, 5, 1, 5, 4, 1, 9, 6, 1,
202 12, 11, 5, 4, 2, 7, 14, 4, 7, 10, 8, 1, 8, 5, 7,
203 14, 2, 3, 3, 11, 1, 7, 5, 1, 11, 10, 7, 9, 8, 1
218 GdPropertyDefault gd_defaults_bd1
[] = {
219 {CAVE_OFFSET(level_amoeba_threshold
), 200},
220 {CAVE_OFFSET(amoeba_growth_prob
), 31250},
221 {CAVE_OFFSET(amoeba_fast_growth_prob
), 250000},
222 {CAVE_OFFSET(amoeba_timer_started_immediately
), TRUE
},
223 {CAVE_OFFSET(amoeba_timer_wait_for_hatching
), FALSE
},
224 {CAVE_OFFSET(lineshift
), TRUE
},
225 {CAVE_OFFSET(wraparound_objects
), TRUE
},
226 {CAVE_OFFSET(diagonal_movements
), FALSE
},
227 {CAVE_OFFSET(voodoo_collects_diamonds
), FALSE
},
228 {CAVE_OFFSET(voodoo_dies_by_stone
), FALSE
},
229 {CAVE_OFFSET(voodoo_disappear_in_explosion
), TRUE
},
230 {CAVE_OFFSET(voodoo_any_hurt_kills_player
), FALSE
},
231 {CAVE_OFFSET(creatures_backwards
), FALSE
},
232 {CAVE_OFFSET(creatures_direction_auto_change_on_start
), FALSE
},
233 {CAVE_OFFSET(creatures_direction_auto_change_time
), 0},
234 {CAVE_OFFSET(level_hatching_delay_time
[0]), 2},
235 {CAVE_OFFSET(intermission_instantlife
), TRUE
},
236 {CAVE_OFFSET(intermission_rewardlife
), FALSE
},
237 {CAVE_OFFSET(magic_wall_stops_amoeba
), TRUE
},
238 {CAVE_OFFSET(magic_timer_wait_for_hatching
), FALSE
},
239 {CAVE_OFFSET(pushing_stone_prob
), 250000},
240 {CAVE_OFFSET(pushing_stone_prob_sweet
), 1000000},
241 {CAVE_OFFSET(active_is_first_found
), FALSE
},
242 {CAVE_OFFSET(short_explosions
), TRUE
},
243 {CAVE_OFFSET(slime_predictable
), TRUE
},
244 {CAVE_OFFSET(snap_element
), O_SPACE
},
245 {CAVE_OFFSET(max_time
), 999},
247 {CAVE_OFFSET(scheduling
), GD_SCHEDULING_BD1
},
248 {CAVE_OFFSET(pal_timing
), TRUE
},
252 GdPropertyDefault gd_defaults_bd2
[] = {
253 {CAVE_OFFSET(level_amoeba_threshold
), 200},
254 {CAVE_OFFSET(amoeba_growth_prob
), 31250},
255 {CAVE_OFFSET(amoeba_fast_growth_prob
), 250000},
256 {CAVE_OFFSET(amoeba_timer_started_immediately
), FALSE
},
257 {CAVE_OFFSET(amoeba_timer_wait_for_hatching
), FALSE
},
258 {CAVE_OFFSET(lineshift
), TRUE
},
259 {CAVE_OFFSET(wraparound_objects
), TRUE
},
260 {CAVE_OFFSET(diagonal_movements
), FALSE
},
261 {CAVE_OFFSET(voodoo_collects_diamonds
), FALSE
},
262 {CAVE_OFFSET(voodoo_dies_by_stone
), FALSE
},
263 {CAVE_OFFSET(voodoo_disappear_in_explosion
), TRUE
},
264 {CAVE_OFFSET(voodoo_any_hurt_kills_player
), FALSE
},
265 {CAVE_OFFSET(creatures_backwards
), FALSE
},
266 {CAVE_OFFSET(creatures_direction_auto_change_on_start
), FALSE
},
267 {CAVE_OFFSET(creatures_direction_auto_change_time
), 0},
268 {CAVE_OFFSET(level_hatching_delay_time
[0]), 2},
269 {CAVE_OFFSET(intermission_instantlife
), TRUE
},
270 {CAVE_OFFSET(intermission_rewardlife
), FALSE
},
271 {CAVE_OFFSET(magic_wall_stops_amoeba
), FALSE
}, /* marek roth bd inside faq 3.0 */
272 {CAVE_OFFSET(magic_timer_wait_for_hatching
), FALSE
},
273 {CAVE_OFFSET(pushing_stone_prob
), 250000},
274 {CAVE_OFFSET(pushing_stone_prob_sweet
), 1000000},
275 {CAVE_OFFSET(active_is_first_found
), FALSE
},
276 {CAVE_OFFSET(short_explosions
), TRUE
},
277 {CAVE_OFFSET(slime_predictable
), TRUE
},
278 {CAVE_OFFSET(snap_element
), O_SPACE
},
279 {CAVE_OFFSET(max_time
), 999},
281 {CAVE_OFFSET(pal_timing
), TRUE
},
282 {CAVE_OFFSET(scheduling
), GD_SCHEDULING_BD2
},
286 GdPropertyDefault gd_defaults_plck
[] = {
287 {CAVE_OFFSET(amoeba_growth_prob
), 31250},
288 {CAVE_OFFSET(amoeba_fast_growth_prob
), 250000},
289 {CAVE_OFFSET(amoeba_timer_started_immediately
), FALSE
},
290 {CAVE_OFFSET(amoeba_timer_wait_for_hatching
), FALSE
},
291 {CAVE_OFFSET(lineshift
), TRUE
},
292 {CAVE_OFFSET(wraparound_objects
), TRUE
},
293 {CAVE_OFFSET(border_scan_first_and_last
), FALSE
},
294 {CAVE_OFFSET(diagonal_movements
), FALSE
},
295 {CAVE_OFFSET(voodoo_collects_diamonds
), FALSE
},
296 {CAVE_OFFSET(voodoo_dies_by_stone
), FALSE
},
297 {CAVE_OFFSET(voodoo_disappear_in_explosion
), TRUE
},
298 {CAVE_OFFSET(voodoo_any_hurt_kills_player
), FALSE
},
299 {CAVE_OFFSET(creatures_backwards
), FALSE
},
300 {CAVE_OFFSET(creatures_direction_auto_change_on_start
), FALSE
},
301 {CAVE_OFFSET(creatures_direction_auto_change_time
), 0},
302 {CAVE_OFFSET(level_hatching_delay_time
[0]), 2},
303 {CAVE_OFFSET(intermission_instantlife
), TRUE
},
304 {CAVE_OFFSET(intermission_rewardlife
), FALSE
},
305 {CAVE_OFFSET(magic_wall_stops_amoeba
), FALSE
},
306 {CAVE_OFFSET(magic_timer_wait_for_hatching
), FALSE
},
307 {CAVE_OFFSET(pushing_stone_prob
), 250000},
308 {CAVE_OFFSET(pushing_stone_prob_sweet
), 1000000},
309 {CAVE_OFFSET(active_is_first_found
), FALSE
},
310 {CAVE_OFFSET(short_explosions
), TRUE
},
311 {CAVE_OFFSET(snap_element
), O_SPACE
},
312 {CAVE_OFFSET(max_time
), 999},
314 {CAVE_OFFSET(pal_timing
), TRUE
},
315 {CAVE_OFFSET(scheduling
), GD_SCHEDULING_PLCK
},
319 GdPropertyDefault gd_defaults_1stb
[] = {
320 {CAVE_OFFSET(amoeba_growth_prob
), 31250},
321 {CAVE_OFFSET(amoeba_fast_growth_prob
), 250000},
322 {CAVE_OFFSET(amoeba_timer_started_immediately
), FALSE
},
323 {CAVE_OFFSET(amoeba_timer_wait_for_hatching
), TRUE
},
324 {CAVE_OFFSET(lineshift
), TRUE
},
325 {CAVE_OFFSET(wraparound_objects
), TRUE
},
326 {CAVE_OFFSET(voodoo_collects_diamonds
), TRUE
},
327 {CAVE_OFFSET(voodoo_dies_by_stone
), TRUE
},
328 {CAVE_OFFSET(voodoo_disappear_in_explosion
), FALSE
},
329 {CAVE_OFFSET(voodoo_any_hurt_kills_player
), FALSE
},
330 {CAVE_OFFSET(creatures_direction_auto_change_on_start
), TRUE
},
331 {CAVE_OFFSET(level_hatching_delay_time
[0]), 2},
332 {CAVE_OFFSET(intermission_instantlife
), FALSE
},
333 {CAVE_OFFSET(intermission_rewardlife
), TRUE
},
334 {CAVE_OFFSET(magic_timer_wait_for_hatching
), TRUE
},
335 {CAVE_OFFSET(pushing_stone_prob
), 250000},
336 {CAVE_OFFSET(pushing_stone_prob_sweet
), 1000000},
337 {CAVE_OFFSET(active_is_first_found
), TRUE
},
338 {CAVE_OFFSET(short_explosions
), FALSE
},
339 {CAVE_OFFSET(slime_predictable
), TRUE
},
340 {CAVE_OFFSET(snap_element
), O_SPACE
},
341 {CAVE_OFFSET(max_time
), 999},
343 {CAVE_OFFSET(pal_timing
), TRUE
},
344 {CAVE_OFFSET(scheduling
), GD_SCHEDULING_PLCK
},
345 {CAVE_OFFSET(amoeba_enclosed_effect
), O_PRE_DIA_1
}, /* not immediately to diamond, but with animation */
346 {CAVE_OFFSET(dirt_looks_like
), O_DIRT2
},
350 GdPropertyDefault gd_defaults_crdr_7
[] = {
351 {CAVE_OFFSET(amoeba_growth_prob
), 31250},
352 {CAVE_OFFSET(amoeba_fast_growth_prob
), 250000},
353 {CAVE_OFFSET(amoeba_timer_started_immediately
), FALSE
},
354 {CAVE_OFFSET(amoeba_timer_wait_for_hatching
), TRUE
},
355 {CAVE_OFFSET(lineshift
), TRUE
},
356 {CAVE_OFFSET(wraparound_objects
), TRUE
},
357 {CAVE_OFFSET(voodoo_collects_diamonds
), TRUE
},
358 {CAVE_OFFSET(voodoo_dies_by_stone
), TRUE
},
359 {CAVE_OFFSET(voodoo_disappear_in_explosion
), FALSE
},
360 {CAVE_OFFSET(voodoo_any_hurt_kills_player
), FALSE
},
361 {CAVE_OFFSET(creatures_direction_auto_change_on_start
), FALSE
},
362 {CAVE_OFFSET(level_hatching_delay_time
[0]), 2},
363 {CAVE_OFFSET(intermission_instantlife
), FALSE
},
364 {CAVE_OFFSET(intermission_rewardlife
), TRUE
},
365 {CAVE_OFFSET(magic_timer_wait_for_hatching
), TRUE
},
366 {CAVE_OFFSET(pushing_stone_prob
), 250000},
367 {CAVE_OFFSET(pushing_stone_prob_sweet
), 1000000},
368 {CAVE_OFFSET(active_is_first_found
), TRUE
},
369 {CAVE_OFFSET(short_explosions
), FALSE
},
370 {CAVE_OFFSET(slime_predictable
), TRUE
},
371 {CAVE_OFFSET(snap_element
), O_SPACE
},
372 {CAVE_OFFSET(max_time
), 999},
374 {CAVE_OFFSET(pal_timing
), TRUE
},
375 {CAVE_OFFSET(scheduling
), GD_SCHEDULING_CRDR
},
376 {CAVE_OFFSET(amoeba_enclosed_effect
), O_PRE_DIA_1
}, /* not immediately to diamond, but with animation */
377 {CAVE_OFFSET(water_does_not_flow_down
), TRUE
},
378 {CAVE_OFFSET(skeletons_worth_diamonds
), 1}, /* in crdr, skeletons can also be used to open the gate */
379 {CAVE_OFFSET(gravity_affects_all
), FALSE
}, /* the intermission "survive" needs this flag */
383 GdPropertyDefault gd_defaults_crli
[] = {
384 {CAVE_OFFSET(amoeba_growth_prob
), 31250},
385 {CAVE_OFFSET(amoeba_fast_growth_prob
), 250000},
386 {CAVE_OFFSET(amoeba_timer_started_immediately
), FALSE
},
387 {CAVE_OFFSET(amoeba_timer_wait_for_hatching
), TRUE
},
388 {CAVE_OFFSET(lineshift
), TRUE
},
389 {CAVE_OFFSET(wraparound_objects
), TRUE
},
390 {CAVE_OFFSET(voodoo_collects_diamonds
), TRUE
},
391 {CAVE_OFFSET(voodoo_dies_by_stone
), TRUE
},
392 {CAVE_OFFSET(voodoo_disappear_in_explosion
), FALSE
},
393 {CAVE_OFFSET(voodoo_any_hurt_kills_player
), FALSE
},
394 {CAVE_OFFSET(creatures_direction_auto_change_on_start
), FALSE
},
395 {CAVE_OFFSET(level_hatching_delay_time
[0]), 2},
396 {CAVE_OFFSET(intermission_instantlife
), FALSE
},
397 {CAVE_OFFSET(intermission_rewardlife
), TRUE
},
398 {CAVE_OFFSET(magic_timer_wait_for_hatching
), TRUE
},
399 {CAVE_OFFSET(pushing_stone_prob
), 250000},
400 {CAVE_OFFSET(pushing_stone_prob_sweet
), 1000000},
401 {CAVE_OFFSET(active_is_first_found
), TRUE
},
402 {CAVE_OFFSET(short_explosions
), FALSE
},
403 {CAVE_OFFSET(slime_predictable
), TRUE
},
404 {CAVE_OFFSET(max_time
), 999},
406 {CAVE_OFFSET(pal_timing
), TRUE
},
407 {CAVE_OFFSET(scheduling
), GD_SCHEDULING_PLCK
},
408 {CAVE_OFFSET(amoeba_enclosed_effect
), O_PRE_DIA_1
}, /* not immediately to diamond, but with animation */
412 /* internal character (letter) codes in c64 games.
413 missing: "triple line" after >, diamond between ()s, player's head after )
414 used for converting names of caves imported from crli and other types of binary data */
415 const char gd_bd_internal_chars
[]=" ,!./0123456789:*<=> ABCDEFGHIJKLMNOPQRSTUVWXYZ( ) _";
417 /* used for bdcff engine flag. */
418 const char *gd_engines
[]={"BD1", "BD2", "PLCK", "1stB", "CrDr", "CrLi"};
423 /* to convert predictable slime values to bit masks */
425 slime_shift_msb(int c64_data
)
430 for (i
=0; i
<c64_data
; i
++)
431 /* shift in this many msb 1's */
432 perm
=(0x100|perm
)>>1;
439 bd1_import(guint8 c
, int i
)
441 if (c
<G_N_ELEMENTS(bd1_import_table
))
442 return bd1_import_table
[c
];
443 g_warning("Invalid BD1 element in imported file at cave data %d: %d", i
, c
);
447 /* deluxe caves 1 contained a special element, non-sloped brick. */
449 deluxecaves_1_import(guint8 c
, int i
)
451 GdElement e
=bd1_import(c
, i
);
453 if (e
==O_H_EXPANDING_WALL
)
454 e
=O_BRICK_NON_SLOPED
;
460 firstboulder_import(guint8 c
, int i
)
462 if (c
<G_N_ELEMENTS(firstboulder_import_table
))
463 return firstboulder_import_table
[c
];
464 g_warning("Invalid 1stB element in imported file at cave data %d: %d", i
, c
);
469 crazylight_import(guint8 c
, int i
)
471 if (c
<G_N_ELEMENTS(gd_crazylight_import_table
))
472 return gd_crazylight_import_table
[c
] & O_MASK
; /* & O_MASK: do not import "scanned" flag */
473 g_warning("Invalid CrLi element in imported file at cave data %d: %d", i
, c
);
481 typedef enum _dirt_mod
{
489 set_dirt_mod (GdCave
*cave
, DirtModType mod_type
)
491 GdElement elem1
, elem2
;
496 /* routine below can check for two different elements; if we need only one,
497 set variables to same value */
505 case DIRT_MOD_AMOEBA
:
506 elem1
=elem2
=O_AMOEBA
;
516 for (y
=0; y
<cave
->h
; y
++)
517 for (x
=0; x
<cave
->w
; x
++)
518 if (cave
->map
[y
][x
]==elem1
|| cave
->map
[y
][x
]==elem2
)
521 for (i
=0; i
<G_N_ELEMENTS(cave
->random_fill
); i
++)
522 if (cave
->random_fill
[i
]==elem1
|| cave
->random_fill
[i
]==elem2
)
524 for (iter
=cave
->objects
; iter
!=NULL
; iter
=iter
->next
) {
525 GdObject
*object
=(GdObject
*) iter
->data
;
527 if (object
->element
==elem1
|| object
->fill_element
==elem1
||
528 object
->element
==elem2
|| object
->fill_element
==elem2
)
532 cave
->dirt_looks_like
=O_DIRT2
;
542 gd_get_engine_default_array(GdEngine engine
)
546 return gd_defaults_bd1
;
549 return gd_defaults_bd2
;
552 return gd_defaults_plck
;
555 return gd_defaults_1stb
;
557 case GD_ENGINE_CRDR7
:
558 return gd_defaults_crdr_7
;
561 return gd_defaults_crli
;
564 /* to avoid compiler warning */
565 case GD_ENGINE_INVALID
:
566 g_assert_not_reached();
570 return gd_defaults_bd1
;
575 gd_cave_set_engine_defaults(GdCave
*cave
, GdEngine engine
)
577 gd_cave_set_defaults_from_array(cave
, gd_get_engine_default_array(engine
));
579 /* these have hardcoded ckdelay. */
580 /* setting this ckdelay array does not fit into the gd_struct_default scheme. */
581 if (engine
==GD_ENGINE_BD1
) {
582 cave
->level_ckdelay
[0]=12;
583 cave
->level_ckdelay
[1]=6;
584 cave
->level_ckdelay
[2]=3;
585 cave
->level_ckdelay
[3]=1;
586 cave
->level_ckdelay
[4]=0;
588 if (engine
==GD_ENGINE_BD2
) {
589 cave
->level_ckdelay
[0]=9; /* 180ms */
590 cave
->level_ckdelay
[1]=8; /* 160ms */
591 cave
->level_ckdelay
[2]=7; /* 140ms */
592 cave
->level_ckdelay
[3]=6; /* 120ms */
593 cave
->level_ckdelay
[4]=6; /* 120ms (!) not faster than level4 */
599 gd_cave_get_engine_from_string(const char *param
)
603 for (i
=0; i
<GD_ENGINE_INVALID
; i
++)
604 if (g_ascii_strcasecmp(param
, gd_engines
[i
])==0)
607 return GD_ENGINE_INVALID
;
612 /****************************************************************************
614 * cave import routines.
615 * take a cave, data, and maybe remaining bytes.
616 * return the number of bytes read, -1 if error.
618 ****************************************************************************/
623 take care of required diamonds values==0 or >100.
624 in original bd, the counter was only two-digit. so bd3 cave f
625 says 150 diamonds required, but you only had to collect 50.
626 also, gate opening is triggered by incrementing diamond
627 count and THEN checking if more required; so if required was
628 0, you had to collect 100. (also check crazy light 8 cave "1000")
630 http://www.boulder-dash.nl/forum/viewtopic.php?t=88
633 /* import bd1 cave data into our format. */
635 cave_copy_from_bd1(GdCave
*cave
, const guint8
*data
, int remaining_bytes
, GdCavefileFormat format
)
637 int length
, direction
;
644 GdElement (* import_func
) (guint8 c
, int i
);
646 gd_error_set_context(cave
->name
);
649 g_assert(format
==GD_FORMAT_BD1
|| format
==GD_FORMAT_DC1
|| format
==GD_FORMAT_BD1_ATARI
);
650 /* cant be shorted than this: header + no objects + delimiter */
651 if (remaining_bytes
<33) {
652 g_critical("truncated BD1 cave data, %d bytes", remaining_bytes
);
656 gd_cave_set_engine_defaults(cave
, GD_ENGINE_BD1
);
657 if (format
==GD_FORMAT_BD1_ATARI
)
658 cave
->scheduling
=GD_SCHEDULING_BD1_ATARI
;
659 if (format
==GD_FORMAT_DC1
)
660 import_func
=deluxecaves_1_import
;
662 import_func
=bd1_import
;
663 /* set visible size for intermission */
664 if (cave
->intermission
) {
669 /* cave number data[0] */
670 cave
->diamond_value
=data
[2];
671 cave
->extra_diamond_value
=data
[3];
673 for (level
=0; level
<5; level
++) {
674 cave
->level_amoeba_time
[level
]=data
[1];
675 if (cave
->level_amoeba_time
[level
]==0) /* 0 immediately underflowed to 999, so we use 999. example: sendydash 3, cave 02. */
676 cave
->level_amoeba_time
[level
]=999;
677 cave
->level_magic_wall_time
[level
]=data
[1];
678 cave
->level_rand
[level
]=data
[4 + level
];
679 cave
->level_diamonds
[level
]=data
[9 + level
] % 100; /* check comment above */
680 if (cave
->level_diamonds
[level
]==0) /* gate opening is checked AFTER adding to diamonds collected, so 0 here means 100 to collect */
681 cave
->level_diamonds
[level
]=100;
682 cave
->level_time
[level
]=data
[14 + level
];
685 /* LogicDeLuxe extension: acid
686 $16 Acid speed (unused in the original BD1)
687 $17 Bit 2: if set, Acid's original position converts to explosion puff during spreading. Otherwise, Acid remains intact, ie. it's just growing. (unused in the original BD1)
688 $1C Acid eats this element. (also Probability of element 1)
690 there is no problem importing these; as other bd1 caves did not contain acid at all, so it does not matter
691 how we set the values.
693 cave
->acid_eats_this
=import_func(data
[0x1c]&0x3F, 0x1c); /* 0x1c index: same as probability1 !!!!! don't be surprised. we do a &0x3f because of this */
694 cave
->acid_spread_ratio
=data
[0x16]/255.0*1E6
+0.5; /* acid speed, *1e6 as probabilities are stored in int */
695 cave
->acid_turns_to
=(data
[0x17]&(1<<2))?O_EXPLODE_3
:O_ACID
;
697 if (format
==GD_FORMAT_BD1_ATARI
) {
699 cave
->color1
=gd_atari_color(data
[0x13]);
700 cave
->color2
=gd_atari_color(data
[0x14]);
701 cave
->color3
=gd_atari_color(data
[0x15]);
702 cave
->color4
=gd_atari_color(data
[0x16]); /* in atari, amoeba was green */
703 cave
->color5
=gd_atari_color(data
[0x16]); /* in atari, slime was green */
704 cave
->colorb
=gd_atari_color(data
[0x17]); /* border = background */
705 cave
->color0
=gd_atari_color(data
[0x17]); /* background */
708 cave
->colorb
=gd_c64_color(0); /* border = background, fixed color */
709 cave
->color0
=gd_c64_color(0); /* background, fixed color */
710 cave
->color1
=gd_c64_color(data
[0x13]&0xf);
711 cave
->color2
=gd_c64_color(data
[0x14]&0xf);
712 cave
->color3
=gd_c64_color(data
[0x15]&0x7); /* lower 3 bits only (vic-ii worked this way) */
713 cave
->color4
=cave
->color3
; /* in bd1, amoeba was color3 */
714 cave
->color5
=cave
->color3
; /* no slime, but let it be color 3 */
718 for (i
=0; i
< 4; i
++) {
719 cave
->random_fill
[i
]=import_func(data
[24+i
], 24+i
);
720 cave
->random_fill_probability
[i
]=data
[28+i
];
724 * Decode the explicit cave data
727 while(data
[index
]!=0xFF && index
<remaining_bytes
&& index
<255) {
729 /* crazy dream 3 extension: */
731 int x1
, y1
, nx
, ny
, dx
, dy
;
734 /* as this one uses nonstandard dx dy values, create points instead */
735 elem
=import_func(data
[index
+1], index
+1);
744 for (x
=0; x
<nx
; x
++) {
745 int pos
=x1
+ y1
*40+ y
*dy
*40 +x
*dx
;
747 cave
->objects
=g_list_append(cave
->objects
, gd_object_new_point(GD_OBJECT_LEVEL_ALL
, pos
%40, pos
/40, elem
));
751 /* object is code&3f, object type is upper 2 bits */
752 elem
=import_func(code
& 0x3F, index
);
754 switch ((code
>> 6) & 3) {
755 case 0: /* 00: POINT */
758 if (x1
>=cave
->w
|| y1
>=cave
->h
)
759 g_warning("invalid point coordinates %d,%d at byte %d", x1
, y1
, index
);
760 cave
->objects
=g_list_append(cave
->objects
, gd_object_new_point(GD_OBJECT_LEVEL_ALL
, x1
, y1
, elem
));
763 case 1: /* 01: LINE */
766 length
=(gint8
)data
[index
+3]-1;
767 direction
=data
[index
+4];
769 g_warning("line length negative, not displaying line at all, at byte %d", index
);
771 if (direction
>MV_UP_LEFT
) {
772 g_warning("invalid line direction %d at byte %d", direction
, index
);
775 x2
=x1
+length
*gd_dx
[direction
+1];
776 y2
=y1
+length
*gd_dy
[direction
+1];
777 if (x1
>=cave
->w
|| y1
>=cave
->h
|| x2
>=cave
->w
|| y2
>=cave
->h
)
778 g_warning("invalid line coordinates %d,%d %d,%d at byte %d", x1
, y1
, x2
, y2
, index
);
779 cave
->objects
=g_list_append(cave
->objects
, gd_object_new_line(GD_OBJECT_LEVEL_ALL
, x1
, y1
, x2
, y2
, elem
));
783 case 2: /* 10: FILLED RECTANGLE */
786 x2
=x1
+data
[index
+3]-1; /* width */
787 y2
=y1
+data
[index
+4]-1; /* height */
788 if (x1
>=cave
->w
|| y1
>=cave
->h
|| x2
>=cave
->w
|| y2
>=cave
->h
)
789 g_warning("invalid filled rectangle coordinates %d,%d %d,%d at byte %d", x1
, y1
, x2
, y2
, index
);
790 cave
->objects
=g_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)));
793 case 3: /* 11: OPEN RECTANGLE (OUTLINE) */
796 x2
=x1
+data
[index
+3]-1;
797 y2
=y1
+data
[index
+4]-1;
798 if (x1
>=cave
->w
|| y1
>=cave
->h
|| x2
>=cave
->w
|| y2
>=cave
->h
)
799 g_warning("invalid rectangle coordinates %d,%d %d,%d at byte %d", x1
, y1
, x2
, y2
, index
);
800 cave
->objects
=g_list_append(cave
->objects
, gd_object_new_rectangle(GD_OBJECT_LEVEL_ALL
, x1
, y1
, x2
, y2
, elem
));
806 if (data
[index
]!=0xFF) {
807 g_critical("import error, cave not delimited with 0xFF");
814 /* import bd2 cave data into our format. return number of bytes if pointer passed.
815 this is pretty much the same as above, only the encoding was different. */
817 cave_copy_from_bd2(GdCave
*cave
, const guint8
*data
, int remaining_bytes
, GdCavefileFormat format
)
822 int x1
, y1
, x2
, y2
, dx
, dy
;
825 g_assert(format
==GD_FORMAT_BD2
|| format
==GD_FORMAT_BD2_ATARI
);
827 gd_error_set_context(cave
->name
);
828 if (remaining_bytes
<0x1A+5) {
829 g_critical("truncated BD2 cave data, %d bytes", remaining_bytes
);
832 gd_cave_set_engine_defaults(cave
, GD_ENGINE_BD2
);
833 if (format
==GD_FORMAT_BD2_ATARI
)
834 cave
->scheduling
=GD_SCHEDULING_BD2_PLCK_ATARI
;
836 /* set visible size for intermission */
837 if (cave
->intermission
) {
842 cave
->diamond_value
=data
[1];
843 cave
->extra_diamond_value
=data
[2];
845 for (i
=0; i
<5; i
++) {
846 /* 0 immediately underflowed to 999, so we use 999. example: sendydash 3, cave 02. */
847 cave
->level_amoeba_time
[i
]=data
[0]==0?999:data
[0];
848 cave
->level_rand
[i
]=data
[13+i
];
849 /* gate opening is checked AFTER adding to diamonds collected, so 0 here is 1000 needed */
850 cave
->level_diamonds
[i
]=data
[8+i
]==0?1000:data
[8+i
];
851 cave
->level_time
[i
]=data
[3+i
];
852 cave
->level_magic_wall_time
[i
]=data
[0];
855 for (i
=0; i
<4; i
++) {
856 cave
->random_fill
[i
]=bd1_import(data
[0x16+i
], 0x16+i
);
857 cave
->random_fill_probability
[i
]=data
[0x12+i
];
861 * Decode the explicit cave data
864 while (data
[index
]!=0xFF && index
<remaining_bytes
) {
868 int length
, direction
;
870 switch (data
[index
]) {
872 elem
=bd1_import(data
[index
+1], index
+1);
875 direction
=data
[index
+4]/2; /* they are multiplied by two - 0 is up, 2 is upright, 4 is right... */
876 length
=data
[index
+5]-1;
877 if (direction
>MV_UP_LEFT
) {
878 g_warning("invalid line direction %d at byte %d", direction
, index
);
881 x2
=x1
+length
*gd_dx
[direction
+1];
882 y2
=y1
+length
*gd_dy
[direction
+1];
883 if (x1
>=cave
->w
|| y1
>=cave
->h
|| x2
>=cave
->w
|| y2
>=cave
->h
)
884 g_warning("invalid line coordinates %d,%d %d,%d at byte %d", x1
, y1
, x2
, y2
, index
);
885 cave
->objects
=g_list_append(cave
->objects
, gd_object_new_line(GD_OBJECT_LEVEL_ALL
, x1
, y1
, x2
, y2
, elem
));
888 case 1: /* OPEN RECTANGLE */
889 elem
=bd1_import(data
[index
+1], index
+1);
892 y2
=y1
+data
[index
+4]-1; /* height */
893 x2
=x1
+data
[index
+5]-1;
894 if (x1
>=cave
->w
|| y1
>=cave
->h
|| x2
>=cave
->w
|| y2
>=cave
->h
)
895 g_warning("invalid rectangle coordinates %d,%d %d,%d at byte %d", x1
, y1
, x2
, y2
, index
);
896 cave
->objects
=g_list_append(cave
->objects
, gd_object_new_rectangle(GD_OBJECT_LEVEL_ALL
, x1
, y1
, x2
, y2
, elem
));
899 case 2: /* FILLED RECTANGLE */
900 elem
=bd1_import(data
[index
+1], index
+1);
903 y2
=y1
+data
[index
+4]-1;
904 x2
=x1
+data
[index
+5]-1;
905 if (x1
>=cave
->w
|| y1
>=cave
->h
|| x2
>=cave
->w
|| y2
>=cave
->h
)
906 g_warning("invalid filled rectangle coordinates %d,%d %d,%d at byte %d", x1
, y1
, x2
, y2
, index
);
907 cave
->objects
=g_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)));
911 elem
=bd1_import(data
[index
+1], index
+1);
914 if (x1
>=cave
->w
|| y1
>=cave
->h
)
915 g_warning("invalid point coordinates %d,%d at byte %d", x1
, y1
, index
);
916 cave
->objects
=g_list_append(cave
->objects
, gd_object_new_point(GD_OBJECT_LEVEL_ALL
, x1
, y1
, elem
));
920 elem
=bd1_import(data
[index
+1], index
+1);
921 y1
=data
[index
+2]; /* starting pos */
923 ny
=data
[index
+4]-1; /* number of elements */
925 dy
=data
[index
+6]; /* displacement */
927 y2
=y1
+dy
*ny
; /* calculate rectangle */
929 if (dy
<1) dy
=1; /* guess this has to be here, after x2,y2 calculation, because of some bugs in imported data */
931 if (x1
>=cave
->w
|| y1
>=cave
->h
|| x2
>=cave
->w
|| y2
>=cave
->h
)
932 g_warning("invalid raster coordinates %d,%d %d,%d at byte %d", x1
, y1
, x2
, y2
, index
);
933 cave
->objects
=g_list_append(cave
->objects
, gd_object_new_raster(GD_OBJECT_LEVEL_ALL
, x1
, y1
, x2
, y2
, dx
, dy
, elem
));
937 /* profi boulder extension: bitmap */
938 elem
=bd1_import(data
[index
+1], index
+1);
939 bytes
=data
[index
+2]; /* number of bytes in bitmap */
940 if (bytes
>=cave
->w
*cave
->h
/8)
941 g_warning("invalid bitmap length at byte %d", index
-4);
943 addr
+=data
[index
+3]; /*msb */
944 addr
+=data
[index
+4] << 8; /*lsb */
945 addr
-=0x0850; /* this was a pointer to the cave work memory (used during game). */
946 if (addr
>=cave
->w
*cave
->h
)
947 g_warning("invalid bitmap start address at byte %d", index
-4);
950 for (i
=0; i
<bytes
; i
++) { /* for ("bytes" number of bytes) */
952 for (n
=0; n
<8; n
++) { /* for (8 bits in a byte) */
953 if ((val
&1)!=0) /* convert to single points... */
954 cave
->objects
=g_list_append(cave
->objects
, gd_object_new_point(GD_OBJECT_LEVEL_ALL
, x1
, y1
, elem
));
956 x1
++; /* next cave pos */
957 if (x1
>=cave
->w
) { /* maybe next line in map */
963 index
+=5+bytes
; /* 5 description bytes and "bytes" data bytes */
967 dx
=data
[index
+3]%40; /* same byte!!! */
968 cave
->objects
=g_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)));
971 case 7: /* SLIME PERMEABILITY */
972 /* interesting this is set here, and not in the cave header */
974 cave
->level_slime_permeability_c64
[i
]=data
[index
+1];
978 /* profi boulder extension by player: plck-like cave map. the import routine (any2gdash) inserts it here. */
979 if (cave
->map
!=NULL
) {
980 g_critical("contains more than one PLCK map");
981 gd_cave_map_free(cave
->map
);
983 cave
->map
=gd_cave_map_new(cave
, GdElement
);
984 for (x
=0; x
<cave
->w
; x
++) {
985 /* fill the first and the last row with steel wall. */
986 cave
->map
[0][x
]=O_STEEL
;
987 cave
->map
[cave
->h
-1][x
]=O_STEEL
;
989 n
=0; /* number of bytes read from map */
990 for (y
=1; y
<cave
->h
-1; y
++) /* the first and the last rows are not stored. */
991 for (x
=0; x
<cave
->w
; x
+=2) {
992 cave
->map
[y
][x
]=plck_import_nybble
[data
[index
+3+n
] >> 4]; /* msb 4 bits */
993 cave
->map
[y
][x
+1]=plck_import_nybble
[data
[index
+3+n
] % 16]; /* lsb 4 bits */
996 /* the position of inbox is stored. this is to check the cave */
999 /* at the start of the cave, bd scrolled to the last player placed during the drawing (setup) of the cave.
1000 i think this is why a map also stored the coordinates of the player - we can use this to check its integrity */
1001 if (rx
>=cave
->w
|| ry
<0 || ry
>=cave
->h
|| cave
->map
[ry
][rx
]!=O_INBOX
)
1002 g_warning ("embedded PLCK map may be corrupted, player coordinates %d,%d", rx
, rx
);
1006 g_warning ("unknown bd2 extension no. %02x at byte %d", data
[index
], index
);
1007 index
+=1; /* skip that byte */
1010 if (data
[index
]!=0xFF) {
1011 g_critical("import error, cave not delimited with 0xFF");
1014 index
++; /* skip delimiter */
1015 index
++; /* animation byte - told the engine which objects to animate - to make game faster */
1017 /* the colors from the memory dump are appended here by any2gdash */
1018 if (format
==GD_FORMAT_BD2
) {
1020 cave
->color0
=gd_c64_color(0);
1021 cave
->color1
=gd_c64_color(data
[index
+0]&0xf);
1022 cave
->color2
=gd_c64_color(data
[index
+1]&0xf);
1023 cave
->color3
=gd_c64_color(data
[index
+2]&0x7); /* lower 3 bits only! */
1024 cave
->color4
=cave
->color1
; /* in bd2, amoeba was color1 */
1025 cave
->color5
=cave
->color1
; /* slime too */
1029 cave
->color1
=gd_atari_color(data
[index
+0]);
1030 cave
->color2
=gd_atari_color(data
[index
+1]);
1031 cave
->color3
=gd_atari_color(data
[index
+2]);
1032 cave
->color4
=gd_atari_color(data
[index
+3]); /* amoeba and slime */
1033 cave
->color5
=gd_atari_color(data
[index
+3]);
1034 cave
->colorb
=gd_atari_color(data
[index
+4]); /* background and border */
1035 cave
->color0
=gd_atari_color(data
[index
+4]);
1042 /* import plck cave data into our format.
1043 length is always 512 bytes, and contains if it is an intermission cave. */
1045 cave_copy_from_plck(GdCave
*cave
, const guint8
*data
, int remaining_bytes
, GdCavefileFormat format
)
1047 /* i don't really think that all this table is needed, but included to be complete. */
1048 /* this is for the dirt and expanding wall looks like effect. */
1049 /* it also contains the individual frames */
1050 static GdElement plck_graphic_table
[]={
1051 /* 3000 */ O_UNKNOWN
, O_UNKNOWN
, O_UNKNOWN
, O_UNKNOWN
, O_UNKNOWN
, O_UNKNOWN
, O_UNKNOWN
, O_UNKNOWN
,
1052 /* 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
,
1053 /* 3200 */ O_AMOEBA
, O_VOODOO
, O_STONE
, O_DIRT
, O_DIAMOND
, O_STEEL
, O_PLAYER
, O_BRICK
,
1054 /* 3300 */ O_SPACE
, O_OUTBOX_OPEN
, O_FIREFLY_1
, O_EXPLODE_1
, O_EXPLODE_2
, O_EXPLODE_3
, O_MAGIC_WALL
, O_MAGIC_WALL
,
1055 /* 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
,
1056 /* 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
,
1057 /* 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
,
1058 /* 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
,
1059 /* 3800 */ O_AMOEBA
, O_AMOEBA
, O_AMOEBA
, O_AMOEBA
, O_AMOEBA
, O_AMOEBA
, O_AMOEBA
, O_AMOEBA
,
1066 g_assert(format
==GD_FORMAT_PLC
|| format
==GD_FORMAT_PLC_ATARI
);
1068 /* hack: check that the "first" (really last - dlp 155) line of the cave is only steel wall. */
1069 /* check from SECOND byte; sometimes the really first byte was a $55, don't know why. that is ignored. */
1071 for (x
=1; x
<20; x
++)
1074 if (data
[0]!=0x44 && data
[0]!=0x55)
1077 if (remaining_bytes
<512) {
1078 g_critical("truncated plck cave data!");
1082 gd_cave_set_engine_defaults(cave
, GD_ENGINE_PLCK
);
1083 if (format
==GD_FORMAT_PLC_ATARI
)
1084 cave
->scheduling
=GD_SCHEDULING_BD2_PLCK_ATARI
;
1085 cave
->intermission
=data
[0x1da]!=0;
1086 if (cave
->intermission
) { /* set visible size for intermission */
1091 /* cave selection table, was not part of cave data, rather given in game packers.
1092 * if a new enough version of any2gdash is used, it will put information after the cave.
1093 * detect this here and act accordingly */
1094 if ((data
[0x1f0]==data
[0x1f1]-1) && (data
[0x1f0]==0x19 || data
[0x1f0]==0x0e)) {
1097 /* found selection table */
1098 cave
->selectable
=data
[0x1f0]==0x19;
1099 gd_strcpy(cave
->name
, " ");
1100 for (j
=0; j
<12; j
++)
1101 cave
->name
[j
]=data
[0x1f2+j
];
1102 g_strchomp(cave
->name
); /* remove spaces */
1104 /* no selection info found, let intermissions be unselectable */
1105 cave
->selectable
=!cave
->intermission
;
1107 cave
->diamond_value
=data
[0x1be];
1108 cave
->extra_diamond_value
=data
[0x1c0];
1109 for (i
=0; i
<5; i
++) {
1110 /* plck doesnot really have levels, so just duplicate data five times */
1111 cave
->level_amoeba_time
[i
]=data
[0x1c4];
1112 if (cave
->level_amoeba_time
[i
]==0) /* immediately underflowed to 999, so we use 999. example: sendydash 3, cave 02. */
1113 cave
->level_amoeba_time
[i
]=999;
1114 cave
->level_time
[i
]=data
[0x1ba];
1115 cave
->level_diamonds
[i
]=data
[0x1bc];
1116 if (cave
->level_diamonds
[i
]==0) /* gate opening is checked AFTER adding to diamonds collected, so 0 here is 1000 needed */
1117 cave
->level_diamonds
[i
]=1000;
1118 cave
->level_ckdelay
[i
]=data
[0x1b8];
1119 cave
->level_magic_wall_time
[i
]=data
[0x1c6];
1120 cave
->level_slime_permeability_c64
[i
]=slime_shift_msb(data
[0x1c2]);
1123 if (format
==GD_FORMAT_PLC_ATARI
) {
1124 /* use atari colors */
1125 cave
->colorb
=gd_atari_color(0); /* border */
1126 /* indexes in data are not the same order as on c64!!! */
1127 cave
->color0
=gd_atari_color(data
[0x1e3]); /* background */
1128 cave
->color1
=gd_atari_color(data
[0x1db]);
1129 cave
->color2
=gd_atari_color(data
[0x1dd]);
1130 cave
->color3
=gd_atari_color(data
[0x1df]);
1131 /* in atari plck, slime and amoeba could not coexist in the same cave. */
1132 /* if amoeba was used, the graphics turned to green, and data at 0x1e1 was set to 0xd4. */
1133 /* if slime was used, graphics to blue, and data at 0x1e1 was set to 0x72. */
1134 /* these two colors could not be changed in the editor at all. */
1135 /* (maybe they could have been changed in a hex editor) */
1136 cave
->color4
=gd_atari_color(data
[0x1e1]);
1137 cave
->color5
=gd_atari_color(data
[0x1e1]);
1139 /* use c64 colors */
1140 cave
->colorb
=gd_c64_color(data
[0x1db]&0xf); /* border */
1141 cave
->color0
=gd_c64_color(data
[0x1dd]&0xf);
1142 cave
->color1
=gd_c64_color(data
[0x1df]&0xf);
1143 cave
->color2
=gd_c64_color(data
[0x1e1]&0xf);
1144 cave
->color3
=gd_c64_color(data
[0x1e3]&0x7); /* lower 3 bits only! */
1145 cave
->color4
=cave
->color3
; /* in plck, amoeba was color3 */
1146 cave
->color5
=cave
->color3
; /* same for slime */
1149 /* ... the cave is stored like a map. */
1150 cave
->map
=gd_cave_map_new(cave
, GdElement
);
1151 /* cave map looked like this. */
1152 /* two rows of steel wall ($44's), then cave description, 20 bytes (40 nybbles) for each line. */
1153 /* the bottom and top lines were not stored... originally. */
1154 /* some games write to the top line; so we import that, too. */
1155 /* also dlp 155 allowed writing to the bottom line; the first 20 $44-s now store the bottom line. */
1156 /* so the cave is essentially shifted one row down in the file: cave->map[y][x]=data[... y+1 mod height ][x] */
1157 for (y
=0; y
<cave
->h
; y
++)
1158 for (x
=0; x
<cave
->w
; x
+=2) {
1159 cave
->map
[y
][x
]=plck_import_nybble
[data
[((y
+1)%cave
->h
)*20 + x
/2] >> 4]; /* msb 4 bits: we do not check index ranges, as >>4 and %16 will result in 0..15 */
1160 cave
->map
[y
][x
+1]=plck_import_nybble
[data
[((y
+1)%cave
->h
)*20 + x
/2] % 16]; /* lsb 4 bits */
1162 /* FOR NOW, WE DO NOT IMPORT THE BOTTOM BORDER */
1163 for (x
=0; x
<cave
->w
; x
++)
1164 cave
->map
[cave
->h
-1][x
]=O_STEEL
;
1166 if (steels && data[0]==0x55)
1167 cave->map[cave->h-1][0]=cave->map[cave->h-1][1]=O_STEEL;
1170 /* check for diego-effects */
1171 /* c64 magic values (byte sequences) 0x20 0x90 0x46, also 0xa9 0x1c 0x85 */
1172 if ((data
[0x1e5]==0x20 && data
[0x1e6]==0x90 && data
[0x1e7]==0x46) || (data
[0x1e5]==0xa9 && data
[0x1e6]==0x1c && data
[0x1e7]==0x85)) {
1173 /* diego effects enabled. */
1174 cave
->stone_bouncing_effect
=bd1_import(data
[0x1ea], 0x1ea);
1175 cave
->diamond_falling_effect
=bd1_import(data
[0x1eb], 0x1eb);
1176 /* explosions: 0x1e was explosion 5, if this is set to default, we also do not read it,
1177 as in our engine this would cause an O_EXPLODE_5 to stay there. */
1178 if (data
[0x1ec]!=0x1e)
1179 cave
->explosion_effect
=bd1_import(data
[0x1ec], 0x1ec);
1180 /* pointer to element graphic.
1181 two bytes/column (one element), that is data[xxx]%16/2.
1182 also there are 16bytes/row.
1183 that is, 0x44=stone, upper left character. 0x45=upper right, 0x54=lower right, 0x55=lower right.
1184 so high nybble must be shifted right twice -> data[xxx]/16*4. */
1185 cave
->dirt_looks_like
=plck_graphic_table
[(data
[0x1ed]/16)*4 + (data
[0x1ed]%16)/2];
1186 cave
->expanding_wall_looks_like
=plck_graphic_table
[(data
[0x1ee]/16)*4 + (data
[0x1ee]%16)/2];
1188 cave
->level_amoeba_threshold
[i
]=data
[0x1ef];
1194 /* no one's delight boulder dash
1195 essentially: rle compressed plck maps. */
1197 cave_copy_from_dlb(GdCave
*cave
, const guint8
*data
, int remaining_bytes
)
1201 START
, /* initial state */
1202 SEPARATOR
, /* got a separator */
1203 RLE
, /* after a separator, got the byte to duplicate */
1204 NORMAL
/* normal, copy bytes till separator */
1206 int pos
, cavepos
, i
, x
, y
;
1207 guint8 byte
, separator
;
1209 gd_error_set_context(cave
->name
);
1210 gd_cave_set_engine_defaults(cave
, GD_ENGINE_PLCK
); /* essentially the plck engine */
1212 for (i
=0; i
<5; i
++) {
1213 /* does not really have levels, so just duplicate data five times */
1214 cave
->level_time
[i
]=data
[1];
1215 cave
->level_diamonds
[i
]=data
[2];
1216 if (cave
->level_diamonds
[i
]==0) /* gate opening is checked AFTER adding to diamonds collected, so 0 here is 1000 needed */
1217 cave
->level_diamonds
[i
]=1000;
1218 cave
->level_ckdelay
[i
]=data
[0];
1219 cave
->level_amoeba_time
[i
]=data
[6];
if (cave
->level_amoeba_time
[i
]==0) /* 0 immediately underflowed to 999, so we use 999. example: sendydash 3, cave 02. */
1220 cave
->level_amoeba_time
[i
]=999;
1221 cave
->level_magic_wall_time
[i
]=data
[7];
1222 cave
->level_slime_permeability_c64
[i
]=slime_shift_msb(data
[5]);
1224 cave
->diamond_value
=data
[3];
1225 cave
->extra_diamond_value
=data
[4];
1227 /* then 5 color bytes follow */
1228 cave
->colorb
=gd_c64_color(data
[8]&0xf); /* border */
1229 cave
->color0
=gd_c64_color(data
[9]&0xf);
1230 cave
->color1
=gd_c64_color(data
[10]&0xf);
1231 cave
->color2
=gd_c64_color(data
[11]&0xf);
1232 cave
->color3
=gd_c64_color(data
[12]&0x7); /* lower 3 bits only! */
1233 cave
->color4
=cave
->color3
; /* in plck, amoeba was color3 */
1234 cave
->color5
=cave
->color3
; /* same for slime */
1237 pos
=13; /* those 13 bytes were the cave values above */
1239 byte
=0; /* just to get rid of compiler warning */
1240 separator
=0; /* just to get rid of compiler warning */
1241 /* employ a state machine. */
1243 while (cavepos
<400 && pos
<remaining_bytes
) {
1246 /* first byte is a separator. remember it */
1247 separator
=data
[pos
];
1248 /* after the first separator, no rle data, just copy. */
1252 /* we had a separator. remember this byte, as this will be duplicated (or more) */
1257 /* we had the first byte, duplicate this n times. */
1258 if (data
[pos
]==0xff) {
1259 /* if it is a 0xff, we will have another byte, which is also a length specifier. */
1260 /* and for this one, duplicate only 254 times */
1261 if (cavepos
+254>400) {
1262 g_critical("DLB import error: RLE data overflows buffer");
1265 for (i
=0; i
<254; i
++)
1266 decomp
[cavepos
++]=byte
;
1268 /* if not 0xff, duplicate n times and back to copy mode */
1269 if (cavepos
+data
[pos
]>400) {
1270 g_critical("DLB import error: RLE data overflows buffer");
1273 for (i
=0; i
<data
[pos
]; i
++)
1274 decomp
[cavepos
++]=byte
;
1279 /* bytes duplicated; now only copy the remaining, till the next separator. */
1280 if (data
[pos
]==separator
)
1283 decomp
[cavepos
++]=data
[pos
]; /* copy this byte and state is still NORMAL */
1289 g_critical("DLB import error: RLE processing, cave length %d, should be 400", cavepos
);
1293 /* process uncompressed map */
1294 cave
->map
=gd_cave_map_new (cave
, GdElement
);
1295 for (x
=0; x
<cave
->w
; x
++) {
1296 /* fill the first and the last row with steel wall. */
1297 cave
->map
[0][x
]=O_STEEL
;
1298 cave
->map
[cave
->h
-1][x
]=O_STEEL
;
1300 for (y
=1; y
<cave
->h
-1; y
++)
1301 for (x
=0; x
<cave
->w
; x
+=2) {
1302 cave
->map
[y
][x
]=plck_import_nybble
[decomp
[((y
-1)*cave
->w
+x
)/2] >> 4]; /* msb 4 bits */
1303 cave
->map
[y
][x
+1]=plck_import_nybble
[decomp
[((y
-1)*cave
->w
+x
)/2] % 16]; /* lsb 4 bits */
1306 /* return number of bytes read from buffer */
1312 /* import plck cave data into our format. */
1314 cave_copy_from_1stb(GdCave
*cave
, const guint8
*data
, int remaining_bytes
)
1319 if (remaining_bytes
<1024) {
1320 g_critical("truncated 1stb cave data!");
1324 gd_cave_set_engine_defaults(cave
, GD_ENGINE_1STB
);
1327 gd_strcpy(cave
->name
, " ");
1328 for (i
=0; i
<14; i
++) {
1329 int c
=data
[0x3a0+i
];
1331 /* import cave name; a conversion table is used for each character */
1333 c
=gd_bd_internal_chars
[c
];
1339 c
=' '; /* don't know this, so change to space */
1341 c
=g_ascii_tolower(c
);
1345 g_strchomp(cave
->name
);
1346 gd_error_set_context(cave
->name
);
1348 cave
->intermission
=data
[0x389]!=0;
1349 /* if it is intermission but not scrollable */
1350 if (cave
->intermission
&& !data
[0x38c]) {
1355 cave
->diamond_value
=100*data
[0x379] + 10*data
[0x379+1] + data
[0x379+2];
1356 cave
->extra_diamond_value
=100*data
[0x376] + 10*data
[0x376+1] + data
[0x376+2];
1357 for (i
=0; i
< 5; i
++) {
1358 /* plck doesnot really have levels, so just duplicate data five times */
1359 cave
->level_time
[i
]=100*data
[0x370] + 10*data
[0x370+1] + data
[0x370+2];
1360 if (cave
->level_time
[i
]==0) /* same as gate opening after 0 diamonds */
1361 cave
->level_time
[i
]=1000;
1362 cave
->level_diamonds
[i
]=100*data
[0x373] + 10*data
[0x373+1] + data
[0x373+2];
1363 if (cave
->level_diamonds
[i
]==0) /* gate opening is checked AFTER adding to diamonds collected, so 0 here is 1000 (!) needed */
1364 cave
->level_diamonds
[i
]=1000;
1365 cave
->level_ckdelay
[i
]=data
[0x38a];
1366 cave
->level_amoeba_time
[i
]=256*(int)data
[0x37c]+data
[0x37d];
1367 if (cave
->level_amoeba_time
[i
]==0) /* 0 immediately underflowed to 999, so we use 999. example: sendydash 3, cave 02. */
1368 cave
->level_amoeba_time
[i
]=999;
1369 cave
->level_magic_wall_time
[i
]=256*(int)data
[0x37e]+data
[0x37f];
1370 cave
->level_slime_permeability_c64
[i
]=data
[0x38b];
1371 cave
->level_bonus_time
[i
]=data
[0x392];
1372 cave
->level_penalty_time
[i
]=data
[0x393];
1373 cave
->level_amoeba_threshold
[i
]=256*(int)data
[0x390] + data
[0x390+1];
1375 /* also has no random data... */
1377 cave
->colorb
=gd_c64_color(data
[0x384]&0xf); /* border */
1378 cave
->color0
=gd_c64_color(data
[0x385]&0xf);
1379 cave
->color1
=gd_c64_color(data
[0x386]&0xf);
1380 cave
->color2
=gd_c64_color(data
[0x387]&0xf);
1381 cave
->color3
=gd_c64_color(data
[0x388]&0x7); /* lower 3 bits only! */
1382 cave
->color4
=cave
->color1
;
1383 cave
->color5
=cave
->color1
;
1385 cave
->amoeba_growth_prob
=(4.0*1E6
/(data
[0x382]+1))+0.5; /* probabilities store *1M */
1386 if (cave
->amoeba_growth_prob
>1000000)
1387 cave
->amoeba_growth_prob
=1000000;
1388 cave
->amoeba_fast_growth_prob
=(4.0*1E6
/(data
[0x383]+1))+0.5;
1389 if (cave
->amoeba_fast_growth_prob
>1000000)
1390 cave
->amoeba_fast_growth_prob
=1000000;
1393 cave
->creatures_direction_auto_change_time
=data
[0x381];
1395 cave
->diagonal_movements
=data
[0x381]!=0;
1397 /* ... the cave is stored like a map. */
1398 cave
->map
=gd_cave_map_new (cave
, GdElement
);
1399 for (y
=0; y
< cave
->h
; y
++)
1400 for (x
=0; x
< cave
->w
; x
++)
1401 cave
->map
[y
][x
]=firstboulder_import(data
[y
*40+x
], y
*40+x
);
1403 cave
->magic_wall_sound
=data
[0x38d]==0xf1;
1404 /* 2d was a normal switch, 2e a changed one. */
1405 cave
->creatures_backwards
=data
[0x38f]==0x2d;
1406 /* 2e horizontal, 2f vertical. */
1407 cave
->expanding_wall_changed
=data
[0x38e]==0x2f;
1409 cave
->biter_delay_frame
=data
[0x394];
1410 cave
->magic_wall_stops_amoeba
=data
[0x395]==0; /* negated!! */
1411 cave
->bomb_explosion_effect
=firstboulder_import(data
[0x396], 0x396);
1412 cave
->explosion_effect
=firstboulder_import(data
[0x397], 0x397);
1413 cave
->stone_bouncing_effect
=firstboulder_import(data
[0x398], 0x398);
1414 cave
->diamond_birth_effect
=firstboulder_import(data
[0x399], 0x399);
1415 cave
->magic_diamond_to
=firstboulder_import(data
[0x39a], 0x39a);
1417 cave
->bladder_converts_by
=firstboulder_import(data
[0x39b], 0x39b);
1418 cave
->diamond_falling_effect
=firstboulder_import(data
[0x39c], 0x39c);
1419 cave
->biter_eat
=firstboulder_import(data
[0x39d], 0x39d);
1420 cave
->slime_eats_1
=firstboulder_import(data
[0x39e], 0x39e);
1421 cave
->slime_converts_1
=firstboulder_import(data
[0x39e]+3, 0x39e);
1422 cave
->slime_eats_2
=firstboulder_import(data
[0x39f], 0x39f);
1423 cave
->slime_converts_2
=firstboulder_import(data
[0x39f]+3, 0x39f);
1424 cave
->magic_diamond_to
=firstboulder_import(data
[0x39a], 0x39a);
1426 /* length is always 1024 bytes */
1433 cave_copy_from_crdr_7(GdCave
*cave
, const guint8
*data
, int remaining_bytes
)
1438 /* if we have name, convert */
1439 gd_strcpy(cave
->name
, " ");
1440 for (i
=0; i
<14; i
++) {
1443 /* import cave name; a conversion table is used for each character */
1445 c
=gd_bd_internal_chars
[c
];
1453 c
=g_ascii_tolower(c
);
1457 g_strchomp(cave
->name
); /* remove trailing and leading spaces */
1458 gd_error_set_context(cave
->name
);
1460 cave
->selectable
=data
[14]!=0;
1462 /* jump 15 bytes, 14 was the name and 15 selectability */
1464 if (memcmp((char *)data
+0x30, "V4\0020", 4)!=0)
1465 g_warning("unknown crdr version %c%c%c%c", data
[0x30], data
[0x31], data
[0x32], data
[0x33]);
1467 gd_cave_set_engine_defaults(cave
, GD_ENGINE_CRDR7
);
1469 for (i
=0; i
<5; i
++) {
1470 cave
->level_time
[i
]=(int)data
[0x0]*100 + data
[0x1]*10 + data
[0x2];
1471 if (cave
->level_time
[i
]==0) /* same as gate opening after 0 diamonds */
1472 cave
->level_time
[i
]=1000;
1473 cave
->level_diamonds
[i
]=(int)data
[0x3]*100+data
[0x4]*10+data
[0x5];
1474 if (cave
->level_diamonds
[i
]==0) /* gate opening is checked AFTER adding to diamonds collected, so 0 here is 1000 (!) needed */
1475 cave
->level_diamonds
[i
]=1000;
1476 cave
->level_ckdelay
[i
]=data
[0x1A];
1477 cave
->level_rand
[i
]=data
[0x40];
1478 cave
->level_amoeba_time
[i
]=(int)data
[0xC] * 256 + data
[0xD];
1479 if (cave
->level_amoeba_time
[i
]==0) /* 0 immediately underflowed to 999, so we use 999. example: sendydash 3, cave 02. */
1480 cave
->level_amoeba_time
[i
]=999;
1481 cave
->level_magic_wall_time
[i
]=(int)data
[0xE] * 256 + data
[0xF];
1482 cave
->level_slime_permeability_c64
[i
]=data
[0x1B];
1483 cave
->level_bonus_time
[i
]=data
[0x22];
1484 cave
->level_penalty_time
[i
]=data
[0x23];
1485 cave
->level_bonus_time
[i
]=data
[0x22];
1486 cave
->level_penalty_time
[i
]=data
[0x23];
1487 cave
->level_amoeba_threshold
[i
]=256*(int)data
[0x20]+data
[0x21];
1489 cave
->extra_diamond_value
=(int)data
[0x6] * 100 + data
[0x7] * 10 + data
[0x8];
1490 cave
->diamond_value
=(int)data
[0x9] * 100 + data
[0xA] * 10 + data
[0xB];
1492 cave
->creatures_direction_auto_change_time
=data
[0x11];
1493 cave
->colorb
=gd_c64_color(data
[0x14]&0xf); /* border */
1494 cave
->color0
=gd_c64_color(data
[0x15]&0xf);
1495 cave
->color1
=gd_c64_color(data
[0x16]&0xf);
1496 cave
->color2
=gd_c64_color(data
[0x17]&0xf);
1497 cave
->color3
=gd_c64_color(data
[0x18]&0x7); /* lower 3 bits only! */
1498 cave
->color4
=cave
->color3
;
1499 cave
->color5
=cave
->color1
;
1500 cave
->intermission
=data
[0x19]!=0;
1501 /* if it is intermission but not scrollable */
1502 if (cave
->intermission
&& !data
[0x1c]) {
1507 /* AMOEBA in crazy dash 8:
1508 jsr $2500 ; generate true random
1509 and $94 ; binary and the current "probability"
1510 cmp #$04 ; compare to 4
1511 bcs out ; jump out (do not expand) if carry set, ie. result was less than 4.
1513 prob values can be like num=3, 7, 15, 31, 63, ... n lsb bits count.
1514 0..3>=4? 0..7>=4? 0..15>=4? and similar.
1515 this way, probability of growing is 4/(num+1)
1517 cave
->amoeba_growth_prob
=(4.0*1E6
/(data
[0x12]+1))+0.5; /* probabilities store *1M */
1518 if (cave
->amoeba_growth_prob
>1000000)
1519 cave
->amoeba_growth_prob
=1000000;
1520 cave
->amoeba_fast_growth_prob
=(4.0*1E6
/(data
[0x13]+1))+0.5;
1521 if (cave
->amoeba_fast_growth_prob
>1000000)
1522 cave
->amoeba_fast_growth_prob
=1000000;
1523 /* expanding wall direction change - 2e horizontal, 2f vertical */
1524 cave
->expanding_wall_changed
=data
[0x1e]==0x2f;
1525 /* 2c was a normal switch, 2d a changed one. */
1526 cave
->creatures_backwards
=data
[0x1f]==0x2d;
1527 cave
->biter_delay_frame
=data
[0x24];
1528 cave
->magic_wall_stops_amoeba
=data
[0x25]==0; /* negated!! */
1529 cave
->bomb_explosion_effect
=crazydream_import_table
[data
[0x26]];
1530 cave
->explosion_effect
=crazydream_import_table
[data
[0x27]];
1531 cave
->stone_bouncing_effect
=crazydream_import_table
[data
[0x28]];
1532 cave
->diamond_birth_effect
=crazydream_import_table
[data
[0x29]];
1533 cave
->magic_diamond_to
=crazydream_import_table
[data
[0x2a]];
1535 cave
->bladder_converts_by
=crazydream_import_table
[data
[0x2b]];
1536 cave
->diamond_falling_effect
=crazydream_import_table
[data
[0x2c]];
1537 cave
->biter_eat
=crazydream_import_table
[data
[0x2d]];
1538 cave
->slime_eats_1
=crazydream_import_table
[data
[0x2e]];
1539 cave
->slime_converts_1
=crazydream_import_table
[data
[0x2e]+3];
1540 cave
->slime_eats_2
=crazydream_import_table
[data
[0x2f]];
1541 cave
->slime_converts_2
=crazydream_import_table
[data
[0x2f]+3];
1543 cave
->diagonal_movements
=(data
[0x34]&1)!=0;
1544 cave
->gravity_change_time
=data
[0x35];
1545 cave
->pneumatic_hammer_frame
=data
[0x36];
1546 cave
->hammered_wall_reappear_frame
=data
[0x37];
1547 cave
->hammered_walls_reappear
=data
[0x3f]!=0;
1549 acid in crazy dream 8:
1550 jsr $2500 ; true random
1551 cmp $03a8 ; compare to ratio
1552 bcs out ; if it was smaller, forget it for now.
1554 ie. random<=ratio, then acid grows.
1556 cave
->acid_spread_ratio
=data
[0x38]/255.0*1E6
+0.5; /* 1e6, probabilities are stored as int */
1557 cave
->acid_eats_this
=crazydream_import_table
[data
[0x39]];
1558 switch(data
[0x3a]&3) {
1559 case 0: cave
->gravity
=MV_UP
; break;
1560 case 1: cave
->gravity
=MV_DOWN
; break;
1561 case 2: cave
->gravity
=MV_LEFT
; break;
1562 case 3: cave
->gravity
=MV_RIGHT
; break;
1564 cave
->snap_element
=((data
[0x3a]&4)!=0)?O_EXPLODE_1
:O_SPACE
;
1565 /* we do not know the values for these, so do not import */
1566 // cave->dirt_looks_like... data[0x3c]
1567 // cave->expanding_wall_looks_like... data[0x3b]
1568 for (i
=0; i
<4; i
++) {
1569 cave
->random_fill
[i
]=crazydream_import_table
[data
[0x41+i
]];
1570 cave
->random_fill_probability
[i
]=data
[0x45+i
];
1575 while (data
[index
]!=0xff) {
1577 int x1
, y1
, x2
, y2
, dx
, dy
;
1579 int length
, direction
;
1580 static int cx1
, cy1
, cw
, ch
; /* for copy&paste; copy&paste are different objects, static=ugly solution :) */
1582 switch(data
[index
]) {
1584 elem
=crazydream_import_table
[data
[index
+1]];
1587 if (x1
>=cave
->w
|| y1
>=cave
->h
)
1588 g_warning("invalid point coordinates %d,%d at byte %d", x1
, y1
, index
);
1589 cave
->objects
=g_list_append(cave
->objects
, gd_object_new_point(GD_OBJECT_LEVEL_ALL
, x1
, y1
, elem
));
1592 case 2: /* rectangle */
1593 elem
=crazydream_import_table
[data
[index
+1]];
1596 x2
=x1
+data
[index
+4]-1;
1597 y2
=y1
+data
[index
+5]-1; /* height */
1598 if (x1
>=cave
->w
|| y1
>=cave
->h
|| x2
>=cave
->w
|| y2
>=cave
->h
)
1599 g_warning("invalid rectangle coordinates %d,%d %d,%d at byte %d", x1
, y1
, x2
, y2
, index
);
1600 cave
->objects
=g_list_append(cave
->objects
, gd_object_new_rectangle(GD_OBJECT_LEVEL_ALL
, x1
, y1
, x2
, y2
, elem
));
1603 case 3: /* fillrect */
1606 x2
=x1
+data
[index
+4]-1;
1607 y2
=y1
+data
[index
+5]-1;
1608 if (x1
>=cave
->w
|| y1
>=cave
->h
|| x2
>=cave
->w
|| y2
>=cave
->h
)
1609 g_warning("invalid filled rectangle coordinates %d,%d %d,%d at byte %d", x1
, y1
, x2
, y2
, index
);
1610 /* border and inside of fill is the same element. */
1611 cave
->objects
=g_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]]));
1616 elem
=crazydream_import_table
[data
[index
+1]];
1617 if (elem
==O_UNKNOWN
)
1618 g_warning("unknown element at %d: %x", index
+1, data
[index
+1]);
1621 length
=data
[index
+4];
1623 direction
=data
[index
+5];
1624 nx
=((signed)direction
-128)%40;
1625 ny
=((signed)direction
-128)/40;
1626 x2
=x1
+(length
-1)*nx
;
1627 y2
=y1
+(length
-1)*ny
;
1628 /* if either is bigger than one, we cannot treat this as a line. create points instead */
1629 if (ABS(nx
)>=2 || ABS(ny
>=2)) {
1630 for (i
=0; i
<length
; i
++) {
1631 cave
->objects
=g_list_append(cave
->objects
, gd_object_new_point(GD_OBJECT_LEVEL_ALL
, x1
, y1
, elem
));
1636 /* this is a normal line, and will be appended. only do the checking here */
1637 if (x1
>=cave
->w
|| y1
>=cave
->h
|| x2
>=cave
->w
|| y2
>=cave
->h
)
1638 g_warning("invalid line coordinates %d,%d %d,%d at byte %d", x1
, y1
, x2
, y2
, index
-5);
1639 cave
->objects
=g_list_append(cave
->objects
, gd_object_new_line(GD_OBJECT_LEVEL_ALL
, x1
, y1
, x2
, y2
, elem
));
1649 if (cx1
>=cave
->w
|| cy1
>=cave
->h
|| cx1
+cw
>cave
->w
|| cy1
+ch
>cave
->h
)
1650 g_warning("invalid copy coordinates %d,%d or size %d,%d at byte %d", cx1
, cy1
, cw
, ch
, index
);
1656 x2
=cx1
+cw
-1; /* original stored width and height, we store the coordinates of the source area */
1658 dx
=data
[index
+1]; /* new pos */
1660 if (dx
>=cave
->w
|| dy
>=cave
->h
|| dx
+cw
>cave
->w
|| dy
+ch
>cave
->h
)
1661 g_warning("invalid paste coordinates %d,%d at byte %d", dx
, dy
, index
);
1662 cave
->objects
=g_list_append(cave
->objects
, gd_object_new_copy_paste(GD_OBJECT_LEVEL_ALL
, x1
, y1
, x2
, y2
, dx
, dy
, FALSE
, FALSE
));
1665 case 11: /* raster */
1666 elem
=crazydream_import_table
[data
[index
+1]];
1673 x2
=x1
+dx
*nx
; /* calculate rectangle we use */
1677 if (x1
>=cave
->w
|| y1
>=cave
->h
|| x2
>=cave
->w
|| y2
>=cave
->h
)
1678 g_warning("invalid raster coordinates %d,%d %d,%d at byte %d", x1
, y1
, x2
, y2
, index
);
1679 cave
->objects
=g_list_append(cave
->objects
, gd_object_new_raster(GD_OBJECT_LEVEL_ALL
, x1
, y1
, x2
, y2
, dx
, dy
, elem
));
1683 g_warning ("unknown crdr extension no. %02x at byte %d", data
[index
], index
);
1684 index
+=1; /* skip that byte */
1688 index
++; /* skip $ff */
1690 /* crazy dream 7 hack */
1692 for (i
=0; i
<0x3b0; i
++)
1693 checksum
=checksum
^data
[i
];
1694 if (g_str_equal(cave
->name
, "Crazy maze") && checksum
==195)
1695 cave
->skeletons_needed_for_pot
=0;
1697 return 15+0x49+index
;
1701 crazy_dream_9_add_specials(GdCave
*cave
, const guint8
*buf
, const int length
)
1706 /* crazy dream 9 hack */
1708 for (i
=0; i
<length
; i
++)
1709 checksum
=checksum
^buf
[i
];
1711 /* check cave name and the checksum. both are hardcoded here */
1712 if (g_str_equal(cave
->name
, "Rockfall") && checksum
==134) {
1713 GdElement rand
[4]={O_DIAMOND
, O_STONE
, O_ACID
, O_DIRT
};
1714 gint32 prob
[4]={37, 32, 2, 0};
1715 gint32 seeds
[5]={-1, -1, -1, -1, -1};
1716 cave
->objects
=g_list_append(cave
->objects
, gd_object_new_random_fill(GD_OBJECT_LEVEL_ALL
, 0, 0, 39, 21, seeds
, O_DIRT
, rand
, prob
, O_BLADDER_SPENDER
, FALSE
));
1719 if (g_str_equal(cave
->name
, "Roll dice now!") && checksum
==235) {
1720 GdElement rand
[4]={O_STONE
, O_BUTTER_3
, O_DIRT
, O_DIRT
};
1721 gint32 prob
[4]={0x18, 0x08, 0, 0};
1722 gint32 seeds
[5]={-1, -1, -1, -1, -1};
1723 cave
->objects
=g_list_append(cave
->objects
, gd_object_new_random_fill(GD_OBJECT_LEVEL_ALL
, 0, 0, 39, 21, seeds
, O_DIRT
, rand
, prob
, O_BLADDER_SPENDER
, FALSE
));
1726 if (g_str_equal(cave
->name
, "Random maze") && checksum
==24) {
1727 gint32 seeds
[5]={-1, -1, -1, -1, -1};
1728 cave
->objects
=g_list_append(cave
->objects
, gd_object_new_maze(GD_OBJECT_LEVEL_ALL
, 1, 4, 35, 20, 1, 1, O_NONE
, O_DIRT
, 50, seeds
));
1731 if (g_str_equal(cave
->name
, "Metamorphosis") && checksum
==53) {
1732 gint32 seeds
[5]={-1, -1, -1, -1, -1};
1733 GdElement rand
[4]={O_STONE
, O_DIRT
, O_DIRT
, O_DIRT
};
1734 gint32 prob
[4]={0x18, 0, 0, 0};
1735 cave
->objects
=g_list_append(cave
->objects
, gd_object_new_maze(GD_OBJECT_LEVEL_ALL
, 4, 1, 38, 19, 1, 3, O_NONE
, O_BLADDER_SPENDER
, 50, seeds
));
1736 cave
->objects
=g_list_append(cave
->objects
, gd_object_new_random_fill(GD_OBJECT_LEVEL_ALL
, 4, 1, 38, 19, seeds
, O_DIRT
, rand
, prob
, O_BLADDER_SPENDER
, FALSE
));
1737 cave
->creatures_backwards
=TRUE
; /* for some reason, this level worked like that */
1740 if (g_str_equal(cave
->name
, "All the way") && checksum
==33) {
1741 gint32 seeds
[5]={-1, -1, -1, -1, -1};
1742 cave
->objects
=g_list_append(cave
->objects
, gd_object_new_maze_unicursal(GD_OBJECT_LEVEL_ALL
, 1, 1, 35, 19, 1, 1, O_BRICK
, O_PRE_DIA_1
, 50, seeds
));
1743 /* a point which "breaks" the unicursal maze, making it one very long path */
1744 cave
->objects
=g_list_append(cave
->objects
, gd_object_new_point(GD_OBJECT_LEVEL_ALL
, 35, 18, O_BRICK
));
1750 /* crazy light contruction kit */
1752 cave_copy_from_crli(GdCave
*cave
, const guint8
*data
, int remaining_bytes
)
1754 guint8 uncompressed
[1024];
1755 int datapos
, cavepos
, i
, x
, y
;
1757 const char *versions
[]={"V2.2", "V2.6", "V3.0"};
1760 V2_2
, /* XXX whats the difference between 2.2 and 2.6?*/
1764 GdElement (*import
) (guint8 c
, int i
)=NULL
; /* import function */
1766 gd_cave_set_engine_defaults(cave
, GD_ENGINE_CRLI
);
1768 /* detect if this is a cavefile */
1769 if (data
[0]==0 && data
[1]==0xc4 && data
[2] == 'D' && data
[3] == 'L' && data
[4] == 'P') {
1770 datapos
=5; /* cavefile, skipping 0x00 0xc4 D L P */
1774 datapos
=15; /* converted from snapshot, skip "selectable" and 14byte name */
1778 /* if we have name, convert */
1780 gd_strcpy(cave
->name
, " ");
1781 for (i
=0; i
<14; i
++) {
1784 /* import cave name; a conversion table is used for each character */
1786 c
=gd_bd_internal_chars
[c
];
1794 c
=g_ascii_tolower(c
);
1798 g_strchomp(cave
->name
); /* remove trailing and leading spaces */
1800 gd_error_set_context(cave
->name
);
1802 /* uncompress rle data */
1804 while (cavepos
<0x3b0) { /* <- loop until the uncompressed reaches its size */
1805 if (datapos
>=remaining_bytes
) {
1806 g_critical("truncated crli cave data");
1809 if (data
[datapos
] == 0xbf) { /* magic value 0xbf is the escape byte */
1810 if (datapos
+2>=remaining_bytes
) {
1811 g_critical("truncated crli cave data");
1814 if(data
[datapos
+2]+datapos
>=sizeof(uncompressed
)) {
1815 /* we would run out of buffer, this must be some error */
1816 g_critical("invalid crli cave data - RLE length value is too big");
1819 /* 0xbf, number, byte to dup */
1820 for (i
=0; i
<data
[datapos
+2]; i
++)
1821 uncompressed
[cavepos
++]=data
[datapos
+1];
1826 uncompressed
[cavepos
++]=data
[datapos
++];
1829 /* check crli version */
1830 for (i
=0; i
<G_N_ELEMENTS(versions
); i
++)
1831 if (memcmp((char *)uncompressed
+0x3a0, versions
[i
], 4)==0)
1834 /* v3.0 has falling wall and box, and no ghost. */
1835 import
= version
>=V3_0
? crazylight_import
:firstboulder_import
;
1837 if (version
==none
) {
1838 g_warning("unknown crli version %c%c%c%c", uncompressed
[0x3a0], uncompressed
[0x3a1], uncompressed
[0x3a2], uncompressed
[0x3a3]);
1839 import
=crazylight_import
;
1843 cave
->map
=gd_cave_map_new (cave
, GdElement
);
1844 for (y
=0; y
<cave
->h
; y
++)
1845 for (x
=0; x
<cave
->w
; x
++) {
1846 int index
=y
*cave
->w
+x
;
1848 cave
->map
[y
][x
]=import(uncompressed
[index
], index
);
1851 /* crli has no levels */
1852 for (i
=0; i
<5; i
++) {
1853 cave
->level_time
[i
]=(int)uncompressed
[0x370] * 100 + uncompressed
[0x371] * 10 + uncompressed
[0x372];
1854 if (cave
->level_time
[i
]==0) /* same as gate opening after 0 diamonds */
1855 cave
->level_time
[i
]=1000;
1856 cave
->level_diamonds
[i
]=(int)uncompressed
[0x373] * 100 + uncompressed
[0x374] * 10 + uncompressed
[0x375];
1857 if (cave
->level_diamonds
[i
]==0) /* gate opening is checked AFTER adding to diamonds collected, so 0 here is 1000 (!) needed */
1858 cave
->level_diamonds
[i
]=1000;
1859 cave
->level_ckdelay
[i
]=uncompressed
[0x38A];
1860 cave
->level_amoeba_time
[i
]=(int)uncompressed
[0x37C] * 256 + uncompressed
[0x37D];
1861 if (cave
->level_amoeba_time
[i
]==0) /* 0 immediately underflowed to 999, so we use 999. example: sendydash 3, cave 02. */
1862 cave
->level_amoeba_time
[i
]=999;
1863 cave
->level_magic_wall_time
[i
]=(int)uncompressed
[0x37E] * 256 + uncompressed
[0x37F];
1864 cave
->level_slime_permeability_c64
[i
]=uncompressed
[0x38B];
1865 cave
->level_bonus_time
[i
]=uncompressed
[0x392];
1866 cave
->level_penalty_time
[i
]=uncompressed
[0x393];
1867 cave
->level_amoeba_threshold
[i
]=256*(int)uncompressed
[0x390]+uncompressed
[0x390+1];
1869 cave
->extra_diamond_value
=(int)uncompressed
[0x376] * 100 + uncompressed
[0x377] * 10 + uncompressed
[0x378];
1870 cave
->diamond_value
=(int)uncompressed
[0x379] * 100 + uncompressed
[0x37A] * 10 + uncompressed
[0x37B];
1871 if (uncompressed
[0x380])
1872 cave
->creatures_direction_auto_change_time
=uncompressed
[0x381];
1873 cave
->colorb
=gd_c64_color(uncompressed
[0x384]&0xf); /* border */
1874 cave
->color0
=gd_c64_color(uncompressed
[0x385]&0xf);
1875 cave
->color1
=gd_c64_color(uncompressed
[0x386]&0xf);
1876 cave
->color2
=gd_c64_color(uncompressed
[0x387]&0xf);
1877 cave
->color3
=gd_c64_color(uncompressed
[0x388]&0x7); /* lower 3 bits only! */
1878 cave
->color4
=cave
->color3
;
1879 cave
->color5
=cave
->color1
;
1880 cave
->intermission
=uncompressed
[0x389]!=0;
1881 /* if it is intermission but not scrollable */
1882 if (cave
->intermission
&& !uncompressed
[0x38c]) {
1887 /* AMOEBA in crazy dash 8:
1888 jsr $2500 ; generate true random
1889 and $94 ; binary and the current "probability"
1890 cmp #$04 ; compare to 4
1891 bcs out ; jump out (do not expand) if carry set, ie. result was less than 4.
1893 prob values can be like num=3, 7, 15, 31, 63, ... n lsb bits count.
1894 0..3>=4? 0..7>=4? 0..15>=4? and similar.
1895 this way, probability of growing is 4/(num+1)
1897 cave
->amoeba_growth_prob
=(1E6
*4.0/(uncompressed
[0x382]+1))+0.5; /* probabilities store *1M */
1898 if (cave
->amoeba_growth_prob
>1000000)
1899 cave
->amoeba_growth_prob
=1000000;
1900 cave
->amoeba_fast_growth_prob
=(1E6
*4.0/(uncompressed
[0x383]+1))+0.5;
1901 if (cave
->amoeba_fast_growth_prob
>1000000)
1902 cave
->amoeba_fast_growth_prob
=1000000;
1903 /* 2c was a normal switch, 2d a changed one. */
1904 cave
->creatures_backwards
=uncompressed
[0x38f]==0x2d;
1905 cave
->magic_wall_sound
=uncompressed
[0x38d]==0xf1;
1906 /* 2e horizontal, 2f vertical. we implement this by changing them */
1907 if (uncompressed
[0x38e]==0x2f)
1908 for (y
=0; y
<cave
->h
; y
++)
1909 for (x
=0; x
<cave
->w
; x
++) {
1910 if (cave
->map
[y
][x
]==O_H_EXPANDING_WALL
)
1911 cave
->map
[y
][x
]=O_V_EXPANDING_WALL
;
1913 cave
->biter_delay_frame
=uncompressed
[0x394];
1914 cave
->magic_wall_stops_amoeba
=uncompressed
[0x395]==0; /* negated!! */
1915 cave
->bomb_explosion_effect
=import(uncompressed
[0x396], 0x396);
1916 cave
->explosion_effect
=import(uncompressed
[0x397], 0x397);
1917 cave
->stone_bouncing_effect
=import(uncompressed
[0x398], 0x398);
1918 cave
->diamond_birth_effect
=import(uncompressed
[0x399], 0x399);
1919 cave
->magic_diamond_to
=import(uncompressed
[0x39a], 0x39a);
1921 cave
->bladder_converts_by
=import(uncompressed
[0x39b], 0x39b);
1922 cave
->diamond_falling_effect
=import(uncompressed
[0x39c], 0x39c);
1923 cave
->biter_eat
=import(uncompressed
[0x39d], 0x39d);
1924 cave
->slime_eats_1
=import(uncompressed
[0x39e], 0x39e);
1925 cave
->slime_converts_1
=import(uncompressed
[0x39e]+3, 0x39e);
1926 cave
->slime_eats_2
=import(uncompressed
[0x39f], 0x39f);
1927 cave
->slime_converts_2
=import(uncompressed
[0x39f]+3, 0x39f);
1929 /* v3.0 has some new properties. */
1930 if (version
>=V3_0
) {
1931 cave
->diagonal_movements
=uncompressed
[0x3a4]!=0;
1932 cave
->amoeba_too_big_effect
=import(uncompressed
[0x3a6], 0x3a6);
1933 cave
->amoeba_enclosed_effect
=import(uncompressed
[0x3a7], 0x3a7);
1935 acid in crazy dream 8:
1936 jsr $2500 ; true random
1937 cmp $03a8 ; compare to ratio
1938 bcs out ; if it was smaller, forget it for now.
1940 ie. random<=ratio, then acid grows.
1942 cave
->acid_spread_ratio
=uncompressed
[0x3a8]/255.0*1E6
; /* *1e6, probabilities are stored as int */
1943 cave
->acid_eats_this
=import(uncompressed
[0x3a9], 0x3a9);
1944 cave
->expanding_wall_looks_like
=import(uncompressed
[0x3ab], 0x3ab);
1945 cave
->dirt_looks_like
=import(uncompressed
[0x3ac], 0x3ac);
1947 /* version is <= 3.0, so this is a 1stb cave. */
1948 /* the only parameters, for which this matters, are these: */
1949 if (uncompressed
[0x380]!=0)
1950 cave
->creatures_direction_auto_change_time
=uncompressed
[0x381];
1952 cave
->diagonal_movements
=uncompressed
[0x381]!=0;
1956 cave
->selectable
=!cave
->intermission
; /* best we can do */
1958 cave
->selectable
=!data
[0]; /* given by converter */
1965 gd_caveset_imported_get_format(const guint8
*buf
)
1967 const char *s_bd1
="GDashBD1";
1968 const char *s_bd1_atari
="GDashB1A";
1969 const char *s_dc1
="GDashDC1";
1970 const char *s_bd2
="GDashBD2";
1971 const char *s_bd2_atari
="GDashB2A";
1972 const char *s_plc
="GDashPLC";
1973 const char *s_plc_atari
="GDashPCA";
1974 const char *s_dlb
="GDashDLB";
1975 const char *s_crl
="GDashCRL";
1976 const char *s_cd7
="GDashCD7";
1977 const char *s_cd9
="GDashCD9";
1978 const char *s_1st
="GDash1ST";
1980 if (memcmp((char *)buf
, s_bd1
, strlen(s_bd1
))==0)
1981 return GD_FORMAT_BD1
;
1982 if (memcmp((char *)buf
, s_bd1_atari
, strlen(s_bd1_atari
))==0)
1983 return GD_FORMAT_BD1_ATARI
;
1984 if (memcmp((char *)buf
, s_dc1
, strlen(s_dc1
))==0)
1985 return GD_FORMAT_DC1
;
1986 if (memcmp((char *)buf
, s_bd2
, strlen(s_bd2
))==0)
1987 return GD_FORMAT_BD2
;
1988 if (memcmp((char *)buf
, s_bd2_atari
, strlen(s_bd2_atari
))==0)
1989 return GD_FORMAT_BD2_ATARI
;
1990 if (memcmp((char *)buf
, s_plc
, strlen(s_plc
))==0)
1991 return GD_FORMAT_PLC
;
1992 if (memcmp((char *)buf
, s_plc_atari
, strlen(s_plc_atari
))==0)
1993 return GD_FORMAT_PLC_ATARI
;
1994 if (memcmp((char *)buf
, s_dlb
, strlen(s_dlb
))==0)
1995 return GD_FORMAT_DLB
;
1996 if (memcmp((char *)buf
, s_crl
, strlen(s_crl
))==0)
1997 return GD_FORMAT_CRLI
;
1998 if (memcmp((char *)buf
, s_cd7
, strlen(s_cd7
))==0)
1999 return GD_FORMAT_CRDR_7
;
2000 if (memcmp((char *)buf
, s_cd9
, strlen(s_cd9
))==0)
2001 return GD_FORMAT_CRDR_9
;
2002 if (memcmp((char *)buf
, s_1st
, strlen(s_1st
))==0)
2003 return GD_FORMAT_FIRSTB
;
2005 return GD_FORMAT_UNKNOWN
;
2010 Load caveset from memory buffer.
2011 Loads the caveset from a memory buffer.
2012 returns: GList * of caves.
2015 gd_caveset_import_from_buffer (const guint8
*buf
, gsize length
)
2018 int cavenum
, intermissionnum
, num
;
2019 int cavelength
, bufp
;
2020 GList
*caveset
=NULL
, *iter
;
2021 guint32 encodedlength
;
2022 GdCavefileFormat format
;
2024 if (length
!=-1 && length
<12) {
2025 g_warning("buffer too short to be a GDash datafile");
2028 encodedlength
=GUINT32_FROM_LE(*((guint32
*)(buf
+8)));
2029 if (length
!=-1 && encodedlength
!=length
-12) {
2030 g_warning("file length and data size mismatch in GDash datafile");
2033 format
=gd_caveset_imported_get_format(buf
);
2034 if (format
==GD_FORMAT_UNKNOWN
) {
2035 g_warning("buffer does not contain a GDash datafile");
2040 length
=encodedlength
;
2045 while (bufp
<length
) {
2047 int insertpos
=-1; /* default is to append cave to caveset; g_list_insert appends when pos=-1 */
2049 newcave
=gd_cave_new();
2051 cavelength
=0; /* to avoid compiler warning */
2054 case GD_FORMAT_BD1
: /* boulder dash 1 */
2055 case GD_FORMAT_BD1_ATARI
: /* boulder dash 1, atari version */
2056 case GD_FORMAT_DC1
: /* deluxe caves 1 */
2057 case GD_FORMAT_BD2
: /* boulder dash 2 */
2058 case GD_FORMAT_BD2_ATARI
: /* boulder dash 2 */
2059 /* these are not in the data so we guess */
2060 newcave
->selectable
=(cavenum
<16) && (cavenum
%4 == 0);
2061 newcave
->intermission
=cavenum
>15;
2062 /* no name, so we make up one */
2063 if (newcave
->intermission
)
2064 g_snprintf(newcave
->name
, sizeof(newcave
->name
), _("Intermission %d"), cavenum
-15);
2066 g_snprintf(newcave
->name
, sizeof(newcave
->name
), _("Cave %c"), 'A'+cavenum
);
2070 case GD_FORMAT_BD1_ATARI
:
2072 cavelength
=cave_copy_from_bd1(newcave
, buf
+bufp
, length
-bufp
, format
);
2075 case GD_FORMAT_BD2_ATARI
:
2076 cavelength
=cave_copy_from_bd2(newcave
, buf
+bufp
, length
-bufp
, format
);
2079 g_assert_not_reached();
2082 /* original bd1 had level order ABCDEFGH... and then the last four were the intermissions.
2083 * those should be inserted between D-E, H-I... caves. */
2085 insertpos
=(cavenum
-15)*5-1;
2088 case GD_FORMAT_FIRSTB
:
2089 cavelength
=cave_copy_from_1stb(newcave
, buf
+bufp
, length
-bufp
);
2090 /* every fifth cave (4+1 intermission) is selectable. */
2091 newcave
->selectable
=cavenum
%5==0;
2094 case GD_FORMAT_PLC
: /* peter liepa construction kit */
2095 case GD_FORMAT_PLC_ATARI
: /* peter liepa construction kit, atari version */
2096 gd_error_set_context("cave %d", cavenum
);
2097 cavelength
=cave_copy_from_plck(newcave
, buf
+bufp
, length
-bufp
, format
);
2100 case GD_FORMAT_DLB
: /* no one's delight boulder dash, something like rle compressed plck caves */
2101 /* but there are 20 of them, as if it was a bd1 or bd2 game. also num%5=4 is intermission. */
2102 /* we have to set intermission flag on our own, as the file did not contain the info explicitly */
2103 newcave
->intermission
=(cavenum
%5)==4;
2104 if (newcave
->intermission
) { /* also set visible size */
2108 newcave
->selectable
=cavenum
% 5 == 0; /* original selection scheme */
2109 if (newcave
->intermission
)
2110 g_snprintf(newcave
->name
, sizeof(newcave
->name
), _("Intermission %d"), cavenum
/5+1);
2112 g_snprintf(newcave
->name
, sizeof(newcave
->name
), _("Cave %c"), 'A'+(cavenum
%5+cavenum
/5*4));
2114 cavelength
=cave_copy_from_dlb (newcave
, buf
+bufp
, length
-bufp
);
2117 case GD_FORMAT_CRLI
:
2118 cavelength
=cave_copy_from_crli (newcave
, buf
+bufp
, length
-bufp
);
2121 case GD_FORMAT_CRDR_7
:
2122 cavelength
=cave_copy_from_crdr_7 (newcave
, buf
+bufp
, length
-bufp
);
2125 case GD_FORMAT_CRDR_9
:
2126 cavelength
=cave_copy_from_crli (newcave
, buf
+bufp
, length
-bufp
);
2128 crazy_dream_9_add_specials(newcave
, buf
, cavelength
);
2131 case GD_FORMAT_UNKNOWN
:
2132 g_assert_not_reached();
2136 gd_error_set_context(NULL
);
2137 if (cavelength
==-1) {
2138 gd_cave_free(newcave
);
2139 g_critical("Aborting cave import.");
2142 caveset
=g_list_insert(caveset
, newcave
, insertpos
);
2146 /* hack: some dlb files contain junk data after 20 caves. */
2147 if (format
==GD_FORMAT_DLB
&& cavenum
==20) {
2149 g_warning("excess data in dlb file, %d bytes", (int)(length
-bufp
));
2154 /* try to detect if plc caves are in standard layout. */
2155 /* that is, caveset looks like an original, (4 cave,1 intermission)+ */
2156 if (format
==GD_FORMAT_PLC
)
2157 /* if no selection table stored by any2gdash */
2158 if ((buf
[2+0x1f0]!=buf
[2+0x1f1]-1) || (buf
[2+0x1f0]!=0x19 && buf
[2+0x1f0]!=0x0e)) {
2163 standard
=(g_list_length(caveset
)%5)==0; /* cave count % 5 != 0 -> nonstandard */
2165 for (n
=0, iter
=caveset
; iter
!=NULL
; n
++, iter
=iter
->next
) {
2166 GdCave
*cave
=iter
->data
;
2168 if ((n
%5==4 && !cave
->intermission
) || (n
%5!=4 && cave
->intermission
))
2169 standard
=FALSE
; /* 4 cave, 1 intermission */
2172 /* if test passed, update selectability */
2174 for (n
=0, iter
=caveset
; iter
!=NULL
; n
++, iter
=iter
->next
) {
2175 GdCave
*cave
=iter
->data
;
2177 /* update "selectable" */
2178 cave
->selectable
=(n
%5)==0;
2182 /* try to give some names for the caves */
2183 cavenum
=1; intermissionnum
=1;
2185 /* use numbering instead of letters, if following formats or too many caves (as we would run out of letters) */
2186 numbering
=format
==GD_FORMAT_PLC
|| format
==GD_FORMAT_CRLI
|| g_list_length(caveset
)>26;
2187 for (iter
=caveset
; iter
!=NULL
; iter
=iter
->next
) {
2188 GdCave
*cave
=(GdCave
*)iter
->data
;
2190 if (!g_str_equal(cave
->name
, "")) /* if it already has a name, skip */
2193 if (cave
->intermission
) {
2196 g_snprintf(cave
->name
, sizeof(cave
->name
), _("Intermission %02d"), num
);
2198 g_snprintf(cave
->name
, sizeof(cave
->name
), _("Intermission %d"), intermissionnum
);
2201 g_snprintf(cave
->name
, sizeof(cave
->name
), _("Cave %02d"), num
);
2203 g_snprintf(cave
->name
, sizeof(cave
->name
), _("Cave %c"), 'A'-1+cavenum
);
2207 if (cave
->intermission
)
2213 gd_error_set_context(NULL
);
2215 /* if the uses requests, we make all caves selectable. intermissions not. */
2216 if (gd_import_as_all_caves_selectable
)
2217 for (iter
=caveset
; iter
!=NULL
; iter
=iter
->next
) {
2218 GdCave
*cave
=(GdCave
*)iter
->data
;
2220 /* make selectable if not an intermission. */
2221 /* also selectable, if it was selectable originally, for some reason. */
2222 cave
->selectable
=cave
->selectable
|| !cave
->intermission
;
2232 /* to be called at program start. */
2234 gd_c64_import_init_tables()
2236 g_assert(gd_defaults_bd1
[G_N_ELEMENTS(gd_defaults_bd1
)-1].offset
==-1);
2237 g_assert(gd_defaults_bd2
[G_N_ELEMENTS(gd_defaults_bd2
)-1].offset
==-1);
2238 g_assert(gd_defaults_plck
[G_N_ELEMENTS(gd_defaults_plck
)-1].offset
==-1);
2239 g_assert(gd_defaults_1stb
[G_N_ELEMENTS(gd_defaults_1stb
)-1].offset
==-1);
2240 g_assert(gd_defaults_crdr_7
[G_N_ELEMENTS(gd_defaults_crdr_7
)-1].offset
==-1);
2241 g_assert(gd_defaults_crli
[G_N_ELEMENTS(gd_defaults_crli
)-1].offset
==-1);