1 /*
2 SDLPoP, a port/conversion of the DOS game Prince of Persia.
3 Copyright (C) 2013-2021  Dávid Nagy
4 
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program.  If not, see <https://www.gnu.org/licenses/>.
17 
18 The authors of this program may be contacted at https://forum.princed.org
19 */
20 
21 #include "common.h"
22 
23 #define SEQTBL_BASE 0x196E
24 #define SEQTBL_0 (seqtbl - SEQTBL_BASE)
25 extern const byte seqtbl[]; // the sequence table is defined in seqtbl.c
26 
27 // seg006:0006
get_tile(int room,int col,int row)28 int __pascal far get_tile(int room,int col,int row) {
29 	curr_room = room;
30 	tile_col = col;
31 	tile_row = row;
32 	curr_room = find_room_of_tile();
33 	// bugfix: check_chomped_kid may call with room = -1
34 	if (curr_room > 0) {
35 		get_room_address(curr_room);
36 		curr_tilepos = tbl_line[tile_row] + tile_col;
37 		curr_tile2 = curr_room_tiles[curr_tilepos] & 0x1F;
38 	} else {
39 		// wall in room 0
40 		curr_tile2 = custom->level_edge_hit_tile; // tiles_20_wall
41 	}
42 	return curr_tile2;
43 }
44 
45 // seg006:005D
find_room_of_tile()46 int __pascal far find_room_of_tile() {
47 	again:
48 #ifdef FIX_CORNER_GRAB
49 	// Check tile_row < 0 first, this way the prince can grab a ledge at the bottom right corner of a room with no room below.
50 	// Details: https://forum.princed.org/viewtopic.php?p=30410#p30410
51 	if (tile_row < 0) {
52 		tile_row += 3;
53 		if (curr_room) {
54 			curr_room = level.roomlinks[curr_room - 1].up;
55 		}
56 		//find_room_of_tile();
57 		goto again;
58 	}
59 #endif
60 	if (tile_col < 0) {
61 		tile_col += 10;
62 		if (curr_room) {
63 			curr_room = level.roomlinks[curr_room - 1].left;
64 		}
65 		//find_room_of_tile();
66 		goto again;
67 	}
68 	if (tile_col >= 10) {
69 		tile_col -= 10;
70 		if (curr_room) {
71 			curr_room = level.roomlinks[curr_room - 1].right;
72 		}
73 		//find_room_of_tile();
74 		goto again;
75 	}
76 #ifndef FIX_CORNER_GRAB
77 	// if (tile_row < 0) was here originally
78 	if (tile_row < 0) {
79 		tile_row += 3;
80 		if (curr_room) {
81 			curr_room = level.roomlinks[curr_room - 1].up;
82 		}
83 		//find_room_of_tile();
84 		goto again;
85 	}
86 #endif
87 	if (tile_row >= 3) {
88 		tile_row -= 3;
89 		if (curr_room) {
90 			curr_room = level.roomlinks[curr_room - 1].down;
91 		}
92 		//find_room_of_tile();
93 		goto again;
94 	}
95 	return curr_room;
96 }
97 
98 // seg006:00EC
get_tilepos(int tile_col,int tile_row)99 int __pascal far get_tilepos(int tile_col,int tile_row) {
100 	if (tile_row < 0) {
101 		return -(tile_col + 1);
102 	} else if (tile_row >= 3 || tile_col >= 10 || tile_col < 0) {
103 		return 30;
104 	} else {
105 		return tbl_line[tile_row] + tile_col;
106 	}
107 }
108 
109 // seg006:0124
get_tilepos_nominus(int tile_col,int tile_row)110 int __pascal far get_tilepos_nominus(int tile_col,int tile_row) {
111 	short var_2;
112 	var_2 = get_tilepos(tile_col, tile_row);
113 	if (var_2 < 0) return 30; else return var_2;
114 }
115 
116 // seg006:0144
load_fram_det_col()117 void __pascal far load_fram_det_col() {
118 	load_frame();
119 	determine_col();
120 }
121 
122 // seg006:014D
determine_col()123 void __pascal far determine_col() {
124 	Char.curr_col = get_tile_div_mod_m7(dx_weight());
125 }
126 
127 // data:0FE0
128 const frame_type frame_table_kid[] = {
129 { 255, 0x00| 0,   0,   0, 0x00| 0},
130 {   0, 0x00| 0,   1,   0, 0xC0| 4},
131 {   1, 0x00| 0,   1,   0, 0x40| 4},
132 {   2, 0x00| 0,   3,   0, 0x40| 7},
133 {   3, 0x00| 0,   4,   0, 0x40| 8},
134 {   4, 0x00| 0,   0,   0, 0xE0| 6},
135 {   5, 0x00| 0,   0,   0, 0x40| 9},
136 {   6, 0x00| 0,   0,   0, 0x40|10},
137 {   7, 0x00| 0,   0,   0, 0xC0| 5},
138 {   8, 0x00| 0,   0,   0, 0x40| 4},
139 {   9, 0x00| 0,   0,   0, 0x40| 7},
140 {  10, 0x00| 0,   0,   0, 0x40|11},
141 {  11, 0x00| 0,   0,   0, 0x40| 3},
142 {  12, 0x00| 0,   0,   0, 0xC0| 3},
143 {  13, 0x00| 0,   0,   0, 0x40| 7},
144 {  14, 0x00| 9,   0,   0, 0x40| 3},
145 {  15, 0x00| 0,   0,   0, 0xC0| 3},
146 {  16, 0x00| 0,   0,   0, 0x40| 4},
147 {  17, 0x00| 0,   0,   0, 0x40| 6},
148 {  18, 0x00| 0,   0,   0, 0x40| 8},
149 {  19, 0x00| 0,   0,   0, 0x80| 9},
150 {  20, 0x00| 0,   0,   0, 0x00|11},
151 {  21, 0x00| 0,   0,   0, 0x80|11},
152 {  22, 0x00| 0,   0,   0, 0x00|17},
153 {  23, 0x00| 0,   0,   0, 0x00| 7},
154 {  24, 0x00| 0,   0,   0, 0x00| 5},
155 {  25, 0x00| 0,   0,   0, 0xC0| 1},
156 {  26, 0x00| 0,   0,   0, 0xC0| 6},
157 {  27, 0x00| 0,   0,   0, 0x40| 3},
158 {  28, 0x00| 0,   0,   0, 0x40| 8},
159 {  29, 0x00| 0,   0,   0, 0x40| 2},
160 {  30, 0x00| 0,   0,   0, 0x40| 2},
161 {  31, 0x00| 0,   0,   0, 0xC0| 2},
162 {  32, 0x00| 0,   0,   0, 0xC0| 2},
163 {  33, 0x00| 0,   0,   0, 0x40| 3},
164 {  34, 0x00| 0,   0,   0, 0x40| 8},
165 {  35, 0x00| 0,   0,   0, 0xC0|14},
166 {  36, 0x00| 0,   0,   0, 0xC0| 1},
167 {  37, 0x00| 0,   0,   0, 0x40| 5},
168 {  38, 0x00| 0,   0,   0, 0x80|14},
169 {  39, 0x00| 0,   0,   0, 0x00|11},
170 {  40, 0x00| 0,   0,   0, 0x80|11},
171 {  41, 0x00| 0,   0,   0, 0x80|10},
172 {  42, 0x00| 0,   0,   0, 0x00| 1},
173 {  43, 0x00| 0,   0,   0, 0xC0| 4},
174 {  44, 0x00| 0,   0,   0, 0xC0| 3},
175 {  45, 0x00| 0,   0,   0, 0xC0| 3},
176 {  46, 0x00| 0,   0,   0, 0xA0| 5},
177 {  47, 0x00| 0,   0,   0, 0xA0| 4},
178 {  48, 0x00| 0,   0,   0, 0x60| 6},
179 {  49, 0x00| 0,   4,   0, 0x60| 7},
180 {  50, 0x00| 0,   3,   0, 0x60| 6},
181 {  51, 0x00| 0,   1,   0, 0x40| 4},
182 {  64, 0x00| 0,   0,   0, 0xC0| 2},
183 {  65, 0x00| 0,   0,   0, 0x40| 1},
184 {  66, 0x00| 0,   0,   0, 0x40| 2},
185 {  67, 0x00| 0,   0,   0, 0x00| 0},
186 {  68, 0x00| 0,   0,   0, 0x00| 0},
187 {  69, 0x00| 0,   0,   0, 0x80| 0},
188 {  70, 0x00| 0,   0,   0, 0x00| 0},
189 {  71, 0x00| 0,   0,   0, 0x80| 0},
190 {  72, 0x00| 0,   0,   0, 0x00| 0},
191 {  73, 0x00| 0,   0,   0, 0x80| 0},
192 {  74, 0x00| 0,   0,   0, 0x00| 0},
193 {  75, 0x00| 0,   0,   0, 0x00| 0},
194 {  76, 0x00| 0,   0,   0, 0x80| 0},
195 { 255, 0x00| 0,   0,   0, 0x00| 0},
196 {  80, 0x00| 0,  -2,   0, 0x40| 1},
197 {  81, 0x00| 0,  -2,   0, 0x40| 1},
198 {  82, 0x00| 0,  -1,   0, 0xC0| 2},
199 {  83, 0x00| 0,  -2,   0, 0x40| 2},
200 {  84, 0x00| 0,  -2,   0, 0x40| 1},
201 {  85, 0x00| 0,  -2,   0, 0x40| 1},
202 {  86, 0x00| 0,  -2,   0, 0x40| 1},
203 {  87, 0x00| 0,  -1,   0, 0x00| 7},
204 {  88, 0x00| 0,  -1,   0, 0x00| 5},
205 {  89, 0x00| 0,   2,   0, 0x00| 7},
206 {  90, 0x00| 0,   2,   0, 0x00| 7},
207 {  91, 0x00| 0,   2,  -3, 0x00| 0},
208 {  92, 0x00| 0,   2, -10, 0x00| 0},
209 {  93, 0x00| 0,   2, -11, 0x80| 0},
210 {  94, 0x00| 0,   3,  -2, 0x40| 3},
211 {  95, 0x00| 0,   3,   0, 0xC0| 3},
212 {  96, 0x00| 0,   3,   0, 0xC0| 3},
213 {  97, 0x00| 0,   3,   0, 0x60| 3},
214 {  98, 0x00| 0,   4,   0, 0xE0| 3},
215 {  28, 0x00| 0,   0,   0, 0x00| 0},
216 {  99, 0x00| 0,   7, -14, 0x80| 0},
217 { 100, 0x00| 0,   7, -12, 0x80| 0},
218 { 101, 0x00| 0,   4, -12, 0x00| 0},
219 { 102, 0x00| 0,   3, -10, 0x80| 0},
220 { 103, 0x00| 0,   2, -10, 0x80| 0},
221 { 104, 0x00| 0,   1, -10, 0x80| 0},
222 { 105, 0x00| 0,   0, -11, 0x00| 0},
223 { 106, 0x00| 0,  -1, -12, 0x00| 0},
224 { 107, 0x00| 0,  -1, -14, 0x00| 0},
225 { 108, 0x00| 0,  -1, -14, 0x00| 0},
226 { 109, 0x00| 0,  -1, -15, 0x80| 0},
227 { 110, 0x00| 0,  -1, -15, 0x80| 0},
228 { 111, 0x00| 0,   0, -15, 0x00| 0},
229 { 255, 0x00| 0,   0,   0, 0x00| 0},
230 { 255, 0x00| 0,   0,   0, 0x00| 0},
231 { 112, 0x00| 0,   0,   0, 0xC0| 6},
232 { 113, 0x00| 0,   0,   0, 0x40| 6},
233 { 114, 0x00| 0,   0,   0, 0xC0| 5},
234 { 115, 0x00| 0,   0,   0, 0x40| 5},
235 { 116, 0x00| 0,   0,   0, 0xC0| 2},
236 { 117, 0x00| 0,   0,   0, 0xC0| 4},
237 { 118, 0x00| 0,   0,   0, 0xC0| 5},
238 { 119, 0x00| 0,   0,   0, 0x40| 6},
239 { 120, 0x00| 0,   0,   0, 0x40| 7},
240 { 121, 0x00| 0,   0,   0, 0x40| 7},
241 { 122, 0x00| 0,   0,   0, 0x40| 9},
242 { 123, 0x00| 0,   0,   0, 0xC0| 8},
243 { 124, 0x00| 0,   0,   0, 0xC0| 9},
244 { 125, 0x00| 0,   0,   0, 0x40| 9},
245 { 126, 0x00| 0,   0,   0, 0x40| 5},
246 { 127, 0x00| 0,   2,   0, 0x40| 5},
247 { 128, 0x00| 0,   2,   0, 0xC0| 5},
248 { 129, 0x00| 0,   0,   0, 0xC0| 3},
249 { 255, 0x00| 0,   0,   0, 0x00| 0},
250 { 133, 0x00| 0,   0,   0, 0x40| 3},
251 { 134, 0x00| 0,   0,   0, 0xC0| 4},
252 { 135, 0x00| 0,   0,   0, 0xC0| 5},
253 { 136, 0x00| 0,   0,   0, 0x40| 8},
254 { 137, 0x00| 0,   0,   0, 0x60|12},
255 { 138, 0x00| 0,   0,   0, 0xE0|15},
256 { 139, 0x00| 0,   0,   0, 0x60| 3},
257 { 140, 0x00| 0,   0,   0, 0xC0| 3},
258 { 141, 0x00| 0,   0,   0, 0x40| 3},
259 { 142, 0x00| 0,   0,   0, 0x40| 3},
260 { 143, 0x00| 0,   0,   0, 0x40| 4},
261 { 144, 0x00| 0,   0,   0, 0x40| 4},
262 { 172, 0x00| 0,   0,   1, 0xC0| 1},
263 { 173, 0x00| 0,   0,   1, 0xC0| 7},
264 { 145, 0x00| 0,   0, -12, 0x00| 1},
265 { 146, 0x00| 0,   0, -21, 0x00| 0},
266 { 147, 0x00| 0,   1, -26, 0x80| 0},
267 { 148, 0x00| 0,   4, -32, 0x80| 0},
268 { 149, 0x00| 0,   6, -36, 0x80| 1},
269 { 150, 0x00| 0,   7, -41, 0x80| 2},
270 { 151, 0x00| 0,   2,  17, 0x40| 2},
271 { 152, 0x00| 0,   4,   9, 0xC0| 4},
272 { 153, 0x00| 0,   4,   5, 0xC0| 9},
273 { 154, 0x00| 0,   4,   4, 0xC0| 8},
274 { 155, 0x00| 0,   5,   0, 0x60| 9},
275 { 156, 0x00| 0,   5,   0, 0xE0| 9},
276 { 157, 0x00| 0,   5,   0, 0xE0| 8},
277 { 158, 0x00| 0,   5,   0, 0x60| 9},
278 { 159, 0x00| 0,   5,   0, 0x60| 9},
279 { 184, 0x00|16,   0,   2, 0x80| 0},
280 { 174, 0x00|26,   0,   2, 0x80| 0},
281 { 175, 0x00|18,   3,   2, 0x00| 0},
282 { 176, 0x00|22,   7,   2, 0xC0| 4},
283 { 177, 0x00|21,  10,   2, 0x00| 0},
284 { 178, 0x00|23,   7,   2, 0x80| 0},
285 { 179, 0x00|25,   4,   2, 0x80| 0},
286 { 180, 0x00|24,   0,   2, 0xC0|14},
287 { 181, 0x00|15,   0,   2, 0xC0|13},
288 { 182, 0x00|20,   3,   2, 0x00| 0},
289 { 183, 0x00|31,   3,   2, 0x00| 0},
290 { 184, 0x00|16,   0,   2, 0x80| 0},
291 { 185, 0x00|17,   0,   2, 0x80| 0},
292 { 186, 0x00|32,   0,   2, 0x00| 0},
293 { 187, 0x00|33,   0,   2, 0x80| 0},
294 { 188, 0x00|34,   2,   2, 0xC0| 3},
295 {  14, 0x00| 0,   0,   0, 0x40| 3},
296 { 189, 0x00|19,   7,   2, 0x80| 0},
297 { 190, 0x00|14,   1,   2, 0x80| 0},
298 { 191, 0x00|27,   0,   2, 0x80| 0},
299 { 181, 0x00|15,   0,   2, 0xC0|13},
300 { 181, 0x00|15,   0,   2, 0xC0|13},
301 { 112, 0x00|43,   0,   0, 0xC0| 6},
302 { 113, 0x00|44,   0,   0, 0x40| 6},
303 { 114, 0x00|45,   0,   0, 0xC0| 5},
304 { 115, 0x00|46,   0,   0, 0x40| 5},
305 { 114, 0x00| 0,   0,   0, 0xC0| 5},
306 {  78, 0x00| 0,   0,   3, 0x80|10},
307 {  77, 0x00| 0,   4,   3, 0x80| 7},
308 { 211, 0x00| 0,   0,   1, 0x40| 4},
309 { 212, 0x00| 0,   0,   1, 0x40| 4},
310 { 213, 0x00| 0,   0,   1, 0x40| 4},
311 { 214, 0x00| 0,   0,   1, 0x40| 7},
312 { 215, 0x00| 0,   0,   7, 0x40|11},
313 { 255, 0x00| 0,   0,   0, 0x00| 0},
314 {  79, 0x00| 0,   4,   7, 0x40| 9},
315 { 130, 0x00| 0,   0,   0, 0x40| 4},
316 { 131, 0x00| 0,   0,   0, 0x40| 4},
317 { 132, 0x00| 0,   0,   2, 0x40| 4},
318 { 255, 0x00| 0,   0,   0, 0x00| 0},
319 { 255, 0x00| 0,   0,   0, 0x00| 0},
320 { 192, 0x00| 0,   0,   0, 0x00| 0},
321 { 193, 0x00| 0,   0,   1, 0x00| 0},
322 { 194, 0x00| 0,   0,   0, 0x80| 0},
323 { 195, 0x00| 0,   0,   0, 0x00| 0},
324 { 196, 0x00| 0,  -1,   0, 0x00| 0},
325 { 197, 0x00| 0,  -1,   0, 0x00| 0},
326 { 198, 0x00| 0,  -1,   0, 0x00| 0},
327 { 199, 0x00| 0,  -4,   0, 0x00| 0},
328 { 200, 0x00| 0,  -4,   0, 0x80| 0},
329 { 201, 0x00| 0,  -4,   0, 0x00| 0},
330 { 202, 0x00| 0,  -4,   0, 0x00| 0},
331 { 203, 0x00| 0,  -4,   0, 0x00| 0},
332 { 204, 0x00| 0,  -4,   0, 0x00| 0},
333 { 205, 0x00| 0,  -5,   0, 0x00| 0},
334 { 206, 0x00| 0,  -5,   0, 0x00| 0},
335 { 255, 0x00| 0,   0,   0, 0x00| 0},
336 { 207, 0x00| 0,   0,   1, 0x40| 6},
337 { 208, 0x00| 0,   0,   1, 0xC0| 6},
338 { 209, 0x00| 0,   0,   1, 0xC0| 8},
339 { 210, 0x00| 0,   0,   1, 0x40|10},
340 { 255, 0x00| 0,   0,   0, 0x00| 0},
341 { 255, 0x00| 0,   0,   0, 0x00| 0},
342 { 255, 0x00| 0,   0,   0, 0x00| 0},
343 { 255, 0x00| 0,   0,   0, 0x00| 0},
344 { 255, 0x00| 0,   0,   0, 0x00| 0},
345 { 255, 0x00| 0,   0,   0, 0x00| 0},
346 {  52, 0x00| 0,   0,   0, 0x80| 0},
347 {  53, 0x00| 0,   0,   0, 0x00| 0},
348 {  54, 0x00| 0,   0,   0, 0x00| 0},
349 {  55, 0x00| 0,   0,   0, 0x00| 0},
350 {  56, 0x00| 0,   0,   0, 0x80| 0},
351 {  57, 0x00| 0,   0,   0, 0x00| 0},
352 {  58, 0x00| 0,   0,   0, 0x00| 0},
353 {  59, 0x00| 0,   0,   0, 0x00| 0},
354 {  60, 0x00| 0,   0,   0, 0x80| 0},
355 {  61, 0x00| 0,   0,   0, 0x00| 0},
356 {  62, 0x00| 0,   0,   0, 0x80| 0},
357 {  63, 0x00| 0,   0,   0, 0x00| 0},
358 { 160, 0x00|35,   1,   1, 0xC0| 3},
359 { 161, 0x00|36,   0,   1, 0x40| 9},
360 { 162, 0x00|37,   0,   1, 0xC0| 3},
361 { 163, 0x00|38,   0,   1, 0x40| 9},
362 { 164, 0x00|39,   0,   1, 0xC0| 3},
363 { 165, 0x00|40,   1,   1, 0x40| 9},
364 { 166, 0x00|41,   1,   1, 0x40| 3},
365 { 167, 0x00|42,   1,   1, 0xC0| 9},
366 { 168, 0x00| 0,   4,   1, 0xC0| 6},
367 { 169, 0x00| 0,   3,   1, 0xC0|10},
368 { 170, 0x00| 0,   1,   1, 0x40| 3},
369 { 171, 0x00| 0,   1,   1, 0xC0| 8},
370 };
371 
372 // data:1496
373 const frame_type frame_tbl_guard[] = {
374 { 255, 0x00| 0,   0,   0, 0x00| 0},
375 {  12, 0xC0|13,   2,   1, 0x00| 0},
376 {   2, 0xC0| 1,   3,   1, 0x00| 0},
377 {   3, 0xC0| 2,   4,   1, 0x00| 0},
378 {   4, 0xC0| 3,   7,   1, 0x40| 4},
379 {   5, 0xC0| 4,  10,   1, 0x00| 0},
380 {   6, 0xC0| 5,   7,   1, 0x80| 0},
381 {   7, 0xC0| 6,   4,   1, 0x80| 0},
382 {   8, 0xC0| 7,   0,   1, 0x80| 0},
383 {   9, 0xC0| 8,   0,   1, 0xC0|13},
384 {  10, 0xC0|11,   7,   1, 0x80| 0},
385 {  11, 0xC0|12,   3,   1, 0x00| 0},
386 {  12, 0xC0|13,   2,   1, 0x00| 0},
387 {  13, 0xC0| 0,   2,   1, 0x00| 0},
388 {  14, 0xC0|28,   0,   1, 0x00| 0},
389 {  15, 0xC0|29,   0,   1, 0x80| 0},
390 {  16, 0xC0|30,   2,   1, 0xC0| 3},
391 {  17, 0xC0| 9,  -1,   1, 0x40| 8},
392 {  18, 0xC0|10,   7,   1, 0x80| 0},
393 {  19, 0xC0|14,   3,   1, 0x80| 0},
394 {   9, 0xC0| 8,   0,   1, 0x80| 0},
395 {  20, 0xC0| 8,   0,   1, 0xC0|13},
396 {  21, 0xC0| 8,   0,   1, 0xC0|13},
397 {  22, 0xC0|47,   0,   0, 0xC0| 6},
398 {  23, 0xC0|48,   0,   0, 0x40| 6},
399 {  24, 0xC0|49,   0,   0, 0xC0| 5},
400 {  24, 0xC0|49,   0,   0, 0xC0| 5},
401 {  24, 0xC0|49,   0,   0, 0xC0| 5},
402 {  26, 0xC0| 0,   0,   3, 0x80|10},
403 {  27, 0xC0| 0,   4,   4, 0x80| 7},
404 {  28, 0xC0| 0,  -2,   1, 0x40| 4},
405 {  29, 0xC0| 0,  -2,   1, 0x40| 4},
406 {  30, 0xC0| 0,  -2,   1, 0x40| 4},
407 {  31, 0xC0| 0,  -2,   2, 0x40| 7},
408 {  32, 0xC0| 0,  -2,   2, 0x40|10},
409 { 255, 0x00| 0,   0,   0, 0x00| 0},
410 {  33, 0xC0| 0,   3,   4, 0xC0| 9},
411 { 255, 0x00| 0,   0,   0, 0x00| 0},
412 { 255, 0x00| 0,   0,   0, 0x00| 0},
413 { 255, 0x00| 0,   0,   0, 0x00| 0},
414 { 255, 0x00| 0,   0,   0, 0x00| 0},
415 };
416 
417 // data:1564
418 const frame_type frame_tbl_cuts[] = {
419 { 255, 0x00| 0,   0,   0, 0x00| 0},
420 {  15, 0x40| 0,   0,   0, 0x00| 0},
421 {   1, 0x40| 0,   0,   0, 0x80| 0},
422 {   2, 0x40| 0,   0,   0, 0x80| 0},
423 {   3, 0x40| 0,   0,   0, 0x80| 0},
424 {   4, 0x40| 0,  -1,   0, 0x00| 0},
425 {   5, 0x40| 0,   2,   0, 0x80| 0},
426 {   6, 0x40| 0,   2,   0, 0x00| 0},
427 {   7, 0x40| 0,   0,   0, 0x80| 0},
428 {   8, 0x40| 0,   1,   0, 0x80| 0},
429 { 255, 0x00| 0,   0,   0, 0x00| 0},
430 {   0, 0x40| 0,   0,   0, 0x80| 0},
431 {   9, 0x40| 0,   0,   0, 0x80| 0},
432 {  10, 0x40| 0,   0,   0, 0x00| 0},
433 {  11, 0x40| 0,   0,   0, 0x80| 0},
434 {  12, 0x40| 0,   0,   0, 0x80| 0},
435 {  13, 0x40| 0,   0,   0, 0x80| 0},
436 {  14, 0x40| 0,   0,   0, 0x00| 0},
437 {  16, 0x40| 0,   0,   0, 0x00| 0},
438 {   0, 0x80| 0,   0,   0, 0x00| 0},
439 {   2, 0x80| 0,   0,   0, 0x00| 0},
440 {   3, 0x80| 0,   0,   0, 0x00| 0},
441 {   4, 0x80| 0,   0,   0, 0x80| 0},
442 {   5, 0x80| 0,   0,   0, 0x00| 0},
443 {   6, 0x80| 0,   0,   0, 0x80| 0},
444 {   7, 0x80| 0,   0,   0, 0x80| 0},
445 {   8, 0x80| 0,   0,   0, 0x00| 0},
446 {   9, 0x80| 0,   0,   0, 0x00| 0},
447 {  10, 0x80| 0,   0,   0, 0x00| 0},
448 {  11, 0x80| 0,   0,   0, 0x00| 0},
449 {  12, 0x80| 0,   0,   0, 0x00| 0},
450 {  13, 0x80| 0,   0,   0, 0x00| 0},
451 {  14, 0x80| 0,   0,   0, 0x00| 0},
452 {  15, 0x80| 0,   0,   0, 0x00| 0},
453 {  16, 0x80| 0,   0,   0, 0x00| 0},
454 {  17, 0x80| 0,   0,   0, 0x00| 0},
455 {  18, 0x80| 0,   0,   0, 0x00| 0},
456 {  19, 0x80| 0,   0,   0, 0x00| 0},
457 {  20, 0x80| 0,   0,   0, 0x80| 0},
458 {  21, 0x80| 0,   0,   0, 0x80| 0},
459 {  22, 0x80| 0,   1,   0, 0x00| 0},
460 {  23, 0x80| 0,  -1,   0, 0x00| 0},
461 {  24, 0x80| 0,   2,   0, 0x00| 0},
462 {  25, 0x80| 0,   1,   0, 0x80| 0},
463 {  26, 0x80| 0,   0,   0, 0x80| 0},
464 {  27, 0x80| 0,   0,   0, 0x80| 0},
465 {  28, 0x80| 0,   0,   0, 0x80| 0},
466 {  29, 0x80| 0,  -1,   0, 0x00| 0},
467 {   0, 0x80| 0,   0,   0, 0x80| 0},
468 {   1, 0x80| 0,   0,   0, 0x80| 0},
469 {   2, 0x80| 0,   0,   0, 0x80| 0},
470 {   3, 0x80| 0,   0,   0, 0x00| 0},
471 {   4, 0x80| 0,   0,   0, 0x00| 0},
472 {   5, 0x80| 0,   0,   0, 0x80| 0},
473 {   6, 0x80| 0,   0,   0, 0x80| 0},
474 {   7, 0x80| 0,   0,   0, 0x80| 0},
475 {   8, 0x80| 0,   0,   0, 0x80| 0},
476 {   9, 0x80| 0,   0,   0, 0x80| 0},
477 {  10, 0x80| 0,   0,   0, 0x80| 0},
478 {  11, 0x80| 0,   0,   0, 0x80| 0},
479 {  12, 0x80| 0,   0,   0, 0x80| 0},
480 {  13, 0x80| 0,   0,   0, 0x00| 0},
481 {  14, 0x80| 0,   0,   0, 0x80| 0},
482 {  15, 0x80| 0,   0,   0, 0x00| 0},
483 {  16, 0x80| 0,   0,   0, 0x00| 0},
484 {  17, 0x80| 0,   0,   0, 0x80| 0},
485 {  18, 0x80| 0,   0,   0, 0x00| 0},
486 {  19, 0x80| 0,   3,   0, 0x00| 0},
487 {  20, 0x80| 0,   3,   0, 0x00| 0},
488 {  21, 0x80| 0,   3,   0, 0x00| 0},
489 {  22, 0x80| 0,   2,   0, 0x00| 0},
490 {  23, 0x80| 0,   3,   0, 0x80| 0},
491 {  24, 0x80| 0,   5,   0, 0x00| 0},
492 {  25, 0x80| 0,   5,   0, 0x00| 0},
493 {  26, 0x80| 0,   1,   0, 0x80| 0},
494 {  27, 0x80| 0,   2,   0, 0x80| 0},
495 {  28, 0x80| 0,   2,   0, 0x80| 0},
496 {  29, 0x80| 0,   1,   0, 0x80| 0},
497 {  30, 0x80| 0,   1,   0, 0x00| 0},
498 {  31, 0x80| 0,   2,   0, 0x00| 0},
499 {  32, 0x80| 0,   3,   0, 0x00| 0},
500 {  33, 0x80| 0,   3,   0, 0x00| 0},
501 {  34, 0x80| 0,   0,   0, 0x80| 0},
502 {  35, 0x80| 0,   2,   0, 0x80| 0},
503 {  36, 0x80| 0,   2,   0, 0x80| 0},
504 {  37, 0x80| 0,   1,   0, 0x00| 0},
505 };
506 
507 
get_frame_internal(const frame_type frame_table[],int frame,const char * frame_table_name,int count)508 void get_frame_internal(const frame_type frame_table[], int frame, const char* frame_table_name, int count) {
509 	if (frame >= 0 && frame < count) {
510 		cur_frame = frame_table[frame];
511 	} else {
512 		printf("Tried to use %s[%d], not in 0..%d\n", frame_table_name, frame, count-1);
513 		static const frame_type blank_frame = {255, 0, 0, 0, 0};
514 		cur_frame = blank_frame;
515 	}
516 }
517 #define get_frame(frame_table, frame) get_frame_internal(frame_table, frame, #frame_table, COUNT(frame_table))
518 
519 // seg006:015A
load_frame()520 void __pascal far load_frame() {
521 	short frame;
522 	short add_frame;
523 	frame = Char.frame;
524 	add_frame = 0;
525 	switch (Char.charid) {
526 		case charid_0_kid:
527 		case charid_24_mouse:
528 		use_table_kid:
529 			get_frame(frame_table_kid, frame);
530 		break;
531 		case charid_2_guard:
532 		case charid_4_skeleton:
533 			if (frame >= 102 && frame < 107) add_frame = 70;
534 			goto use_table_guard;
535 		case charid_1_shadow:
536 			if (frame < 150 || frame >= 190) goto use_table_kid;
537 		use_table_guard:
538 			get_frame(frame_tbl_guard, frame + add_frame - 149);
539 		break;
540 		case charid_5_princess:
541 		case charid_6_vizier:
542 //		use_table_cutscene:
543 			get_frame(frame_tbl_cuts, frame);
544 		break;
545 	}
546 }
547 #undef get_frame
548 
549 // seg006:01F5
dx_weight()550 short __pascal far dx_weight() {
551 	sbyte var_2;
552 	var_2 = cur_frame.dx - (cur_frame.flags & FRAME_WEIGHT_X);
553 	return char_dx_forward(var_2);
554 }
555 
556 // seg006:0213
char_dx_forward(int delta_x)557 int __pascal far char_dx_forward(int delta_x) {
558 	if (Char.direction < dir_0_right) {
559 		delta_x = -delta_x;
560 	}
561 	return delta_x + Char.x;
562 }
563 
564 // seg006:0234
obj_dx_forward(int delta_x)565 int __pascal far obj_dx_forward(int delta_x) {
566 	if (obj_direction < dir_0_right) {
567 		delta_x = -delta_x;
568 	}
569 	obj_x += delta_x;
570 	return obj_x;
571 }
572 
573 // seg006:0254
play_seq()574 void __pascal far play_seq() {
575 	for (;;) {
576 		byte item = *(SEQTBL_0 + Char.curr_seq++);
577 		switch (item) {
578 			case SEQ_DX: // dx
579 				Char.x = char_dx_forward(*(SEQTBL_0 + Char.curr_seq++));
580 				break;
581 			case SEQ_DY: // dy
582 				Char.y += *(SEQTBL_0 + Char.curr_seq++);
583 				break;
584 			case SEQ_FLIP: // flip
585 				Char.direction = ~Char.direction;
586 				break;
587 			case SEQ_JMP_IF_FEATHER: // jump if feather
588 				if (!is_feather_fall) {
589 					++Char.curr_seq;
590 					++Char.curr_seq;
591 					break;
592 				}
593 				// fallthrough!
594 			case SEQ_JMP: // jump
595 				Char.curr_seq = *(const word*)(SEQTBL_0 + Char.curr_seq);
596 				break;
597 			case SEQ_UP: // up
598 				--Char.curr_row;
599 				start_chompers();
600 				break;
601 			case SEQ_DOWN: // down
602 				inc_curr_row();
603 				start_chompers();
604 				break;
605 			case SEQ_ACTION: // action
606 				Char.action = *(SEQTBL_0 + Char.curr_seq++);
607 				break;
608 			case SEQ_SET_FALL: // set fall
609 				Char.fall_x = *(SEQTBL_0 + Char.curr_seq++);
610 				Char.fall_y = *(SEQTBL_0 + Char.curr_seq++);
611 				break;
612 			case SEQ_KNOCK_UP: // knock up
613 				knock = 1;
614 				break;
615 			case SEQ_KNOCK_DOWN: // knock down
616 				knock = -1;
617 				break;
618 			case SEQ_SOUND: // sound
619 				switch (*(SEQTBL_0 + Char.curr_seq++)) {
620 					case SND_SILENT: // no sound actually played, but guards still notice the kid
621 						is_guard_notice = 1;
622 						break;
623 					case SND_FOOTSTEP: // feet
624 						play_sound(sound_23_footstep); // footstep
625 						is_guard_notice = 1;
626 						break;
627 					case SND_BUMP: // bump
628 						play_sound(sound_8_bumped); // touching a wall
629 						is_guard_notice = 1;
630 						break;
631 					case SND_DRINK: // drink
632 						play_sound(sound_18_drink); // drink
633 						break;
634 					case SND_LEVEL: // level
635 #ifdef USE_REPLAY
636 						if (recording || replaying) break; // don't do end level music in replays
637 #endif
638 
639 						if (is_sound_on) {
640 							if (current_level == 4) {
641 								play_sound(sound_32_shadow_music); // end level with shadow (level 4)
642 							} else if (current_level != 13 && current_level != 15) {
643 								play_sound(sound_41_end_level_music); // end level
644 							}
645 						}
646 						break;
647 				}
648 				break;
649 			case SEQ_END_LEVEL: // end level
650 				++next_level;
651 #ifdef USE_REPLAY
652 				// Preserve the seed in this frame, to ensure reproducibility of the replay in the next level,
653 				// regardless of how long the sound is still playing *after* this frame.
654 				// Animations (e.g. torch) can change the seed!
655 				keep_last_seed = 1;
656 				if (replaying && skipping_replay) stop_sounds();
657 #endif
658 				break;
659 			case SEQ_GET_ITEM: // get item
660 				if (*(SEQTBL_0 + Char.curr_seq++) == 1) {
661 					proc_get_object();
662 				}
663 				break;
664 			case SEQ_DIE: // nop
665 				break;
666 			default:
667 				Char.frame = item;
668 				//if (Char.frame == 185) Char.frame = 185;
669 				return;
670 		}
671 	}
672 }
673 
674 // seg006:03DE
get_tile_div_mod_m7(int xpos)675 int __pascal far get_tile_div_mod_m7(int xpos) {
676 	return get_tile_div_mod(xpos - 7);
677 }
678 
679 // data:22A6
680 const sbyte tile_div_tbl[256] = {
681                                     -5,-5,
682 -4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,
683 -3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,
684 -2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,
685 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
686  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
687  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
688  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
689  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
690  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
691  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
692  6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
693  7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
694  8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
695  9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
696 10,10,10,10,10,10,10,10,10,10,10,10,10,10,
697 11,11,11,11,11,11,11,11,11,11,11,11,11,11,
698 12,12,12,12,12,12,12,12,12,12,12,12,12,12,
699 13,13,13,13,13,13,13,13,13,13,13,13,13,13,
700 14,14
701 };
702 
703 // data:23A6
704 const byte tile_mod_tbl[256] = {
705                                       12, 13,
706 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
707 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
708 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
709 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
710 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
711 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
712 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
713 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
714 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
715 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
716 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
717 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
718 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
719 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
720 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
721 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
722 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
723 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
724 0, 1
725 };
726 
727 // seg006:03F0
get_tile_div_mod(int xpos)728 int __pascal far get_tile_div_mod(int xpos) {
729 	// Determine tile column (xh) and the position within the tile (xl) from xpos.
730 
731 // DOS PoP does this:
732 //	obj_xl = tile_mod_tbl[xpos];
733 //	return tile_div_tbl[xpos];
734 
735 	// xpos uses a coordinate system in which the left edge of the screen is 58, and each tile is 14 units wide.
736 	int x = xpos - 58;
737 	int xl = x % 14;
738 	int xh = x / 14;
739 	if (xl < 0) {
740 		// Integer division rounds towards zero, but we want to round down.
741 		--xh;
742 		// Modulo returns a negative number if x is negative, but we want 0 <= xl < 14.
743 		xl += 14;
744 	}
745 
746 	// For compatibility with the DOS version, we allow for overflow access to these tables
747 	// Considering the case of negative overflow
748 	if (xpos < 0) {
749 		// In this case DOS PoP reads the bytes directly before tile_div_tbl[] and tile_mod_tbl[] in the memory.
750 		// Here we simulate these reads.
751 		// Before tile_mod_tbl[] is tile_div_tbl[], and before tile_div_tbl[] are the following bytes:
752 		static const byte bogus[] = {0x02, 0x00, 0x41, 0x00, 0x80, 0x00, 0xBF, 0x00, 0xFE, 0x00, 0xFF, 0x01, 0x01, 0xFF, 0xC4, 0xFF, 0x03, 0x00, 0x42, 0x00, 0x81, 0x00, 0xC0, 0x00, 0xF8, 0xFF, 0x37, 0x00, 0x76, 0x00, 0xB5, 0x00, 0xF4, 0x00};
753 		if (COUNT(bogus) + xpos >= 0) {
754 			xh = bogus[COUNT(bogus) + xpos]; // simulating tile_div_tbl[xpos]
755 			xl = tile_div_tbl[COUNT(tile_div_tbl) + xpos]; // simulating tile_mod_tbl[xpos]
756 		} else {
757 			printf("xpos = %d (< %d) out of range for simulation of index overflow!\n", xpos, -(int)COUNT(bogus));
758 		}
759 	}
760 
761 	// Considering the case of positive overflow
762 	int tblSize = 256;
763 
764  if (xpos >= tblSize) {
765   // In this case DOS PoP reads the bytes directly after tile_div_tbl[], that is: and tile_mod_tbl[]
766   // Here we simulate these reads.
767   // After tile_mod_tbl[] there are the following bytes:
768   static const byte bogus[] = {0xF4, 0x02, 0x10, 0x1E, 0x2C, 0x3A, 0x48, 0x56, 0x64, 0x72, 0x80, 0x8E, 0x9C, 0xAA, 0xB8, 0xC6, 0xD4, 0xE2, 0xF0, 0xFE, 0x00, 0x0A, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x0D, 0x00, 0x00, 0x00, 0x00};
769   if (xpos-tblSize < COUNT(bogus)) {
770    xh = tile_mod_tbl[xpos-tblSize]; // simulating tile_div_tbl[xpos]
771    xl = bogus[xpos-tblSize]; // simulating tile_mod_tbl[xpos]
772   } else {
773    printf("xpos = %d (> %d) out of range for simulation of index overflow!\n", xpos, (int)COUNT(bogus)+tblSize);
774   }
775  }
776 
777 	obj_xl = xl;
778 	return xh;
779 }
780 
781 // seg006:0433
y_to_row_mod4(int ypos)782 int __pascal far y_to_row_mod4(int ypos) {
783 	return (ypos + 60) / 63 % 4 - 1;
784 }
785 
786 // seg006:044F
loadkid()787 void __pascal far loadkid() {
788 	Char = Kid;
789 }
790 
791 // seg006:0464
savekid()792 void __pascal far savekid() {
793 	Kid = Char;
794 }
795 
796 // seg006:0479
loadshad()797 void __pascal far loadshad() {
798 	Char = Guard;
799 }
800 
801 // seg006:048E
saveshad()802 void __pascal far saveshad() {
803 	Guard = Char;
804 }
805 
806 // seg006:04A3
loadkid_and_opp()807 void __pascal far loadkid_and_opp() {
808 	loadkid();
809 	Opp = Guard;
810 }
811 
812 // seg006:04BC
savekid_and_opp()813 void __pascal far savekid_and_opp() {
814 	savekid();
815 	Guard = Opp;
816 }
817 
818 // seg006:04D5
loadshad_and_opp()819 void __pascal far loadshad_and_opp() {
820 	loadshad();
821 	Opp = Kid;
822 }
823 
824 // seg006:04EE
saveshad_and_opp()825 void __pascal far saveshad_and_opp() {
826 	saveshad();
827 	Kid = Opp;
828 }
829 
830 // seg006:0507
reset_obj_clip()831 void __pascal far reset_obj_clip() {
832 	obj_clip_left = 0;
833 	obj_clip_top = 0;
834 	obj_clip_right = 320;
835 	obj_clip_bottom = 192;
836 }
837 
838 // seg006:051C
x_to_xh_and_xl(int xpos,sbyte * xh_addr,sbyte * xl_addr)839 void __pascal far x_to_xh_and_xl(int xpos, sbyte *xh_addr, sbyte *xl_addr) {
840 	if (xpos < 0) {
841 		*xh_addr = -((ABS(-xpos) >> 3) + 1);
842 		*xl_addr = - ((-xpos - 1) % 8 - 7);
843 	} else {
844 		*xh_addr = ABS(xpos) >> 3;
845 		*xl_addr = xpos % 8;
846 	}
847 }
848 
849 // seg006:057C
fall_accel()850 void __pascal far fall_accel() {
851 	if (Char.action == actions_4_in_freefall) {
852 		if (is_feather_fall) {
853 			++Char.fall_y;
854 			if (Char.fall_y > 4) Char.fall_y = 4;
855 		} else {
856 			Char.fall_y += 3;
857 			if (Char.fall_y > 33) Char.fall_y = 33;
858 		}
859 	}
860 }
861 
862 // seg006:05AE
fall_speed()863 void __pascal far fall_speed() {
864 	Char.y += Char.fall_y;
865 	if (Char.action == actions_4_in_freefall) {
866 		Char.x = char_dx_forward(Char.fall_x);
867 		load_fram_det_col();
868 	}
869 }
870 
871 // seg006:05CD
check_action()872 void __pascal far check_action() {
873 	short frame;
874 	short action;
875 	action = Char.action;
876 	frame = Char.frame;
877 	// frame 109: crouching
878 	if (action == actions_6_hang_straight ||
879 		action == actions_5_bumped
880 	) {
881 		if (frame == frame_109_crouch
882 
883 			#ifdef FIX_STAND_ON_THIN_AIR
884 			|| (fixes->fix_stand_on_thin_air &&
885 				frame >= frame_110_stand_up_from_crouch_1 && frame <= frame_119_stand_up_from_crouch_10)
886 			#endif
887 
888 				) {
889 			check_on_floor();
890 		}
891 	} else if (action == actions_4_in_freefall) {
892 		do_fall();
893 	} else if (action == actions_3_in_midair) {
894 		// frame 102..106: start fall + fall
895 		if (frame >= frame_102_start_fall_1 && frame < frame_106_fall) {
896 			check_grab();
897 		}
898 	} else if (action != actions_2_hang_climb) {
899 		check_on_floor();
900 	}
901 }
902 
903 // seg006:0628
tile_is_floor(int tiletype)904 int __pascal far tile_is_floor(int tiletype) {
905 	switch (tiletype) {
906 		case tiles_0_empty:
907 		case tiles_9_bigpillar_top:
908 		case tiles_12_doortop:
909 		case tiles_20_wall:
910 		case tiles_26_lattice_down:
911 		case tiles_27_lattice_small:
912 		case tiles_28_lattice_left:
913 		case tiles_29_lattice_right:
914 			return 0;
915 		default:
916 			return 1;
917 	}
918 }
919 
920 // seg006:0658
check_spiked()921 void __pascal far check_spiked() {
922 	short harmful;
923 	short frame;
924 	frame = Char.frame;
925 	if (get_tile(Char.room, Char.curr_col, Char.curr_row) == tiles_2_spike) {
926 		harmful = is_spike_harmful();
927 		// frames 7..14: running
928 		// frames 34..39: start run-jump
929 		// frame 43: land from run-jump
930 		// frame 26: lang from standing jump
931 		if (
932 			(harmful >= 2 && ((frame>= frame_7_run && frame<15) || (frame>=frame_34_start_run_jump_1 && frame<40))) ||
933 			((frame == frame_43_running_jump_4 || frame == frame_26_standing_jump_11) && harmful != 0)
934 		) {
935 			spiked();
936 		}
937 	}
938 }
939 
940 // seg006:06BD
take_hp(int count)941 int __pascal far take_hp(int count) {
942 	word dead;
943 	dead = 0;
944 	if (Char.charid == charid_0_kid) {
945 		if (count >= hitp_curr) {
946 			hitp_delta = -hitp_curr;
947 			dead = 1;
948 		} else {
949 			hitp_delta = -count;
950 		}
951 	} else {
952 		if (count >= guardhp_curr) {
953 			guardhp_delta = -guardhp_curr;
954 			dead = 1;
955 		} else {
956 			guardhp_delta = -count;
957 		}
958 	}
959 	return dead;
960 }
961 
962 // seg006:070D
get_tile_at_char()963 int __pascal far get_tile_at_char() {
964 	return get_tile(Char.room, Char.curr_col, Char.curr_row);
965 }
966 
967 // seg006:0723
set_char_collision()968 void __pascal far set_char_collision() {
969 	image_type* image = get_image(obj_chtab, obj_id);
970 	if (image == NULL) {
971 		char_width_half = 0;
972 		char_height = 0;
973 	} else {
974 		char_width_half = (image->/*width*/w + 1) / 2;
975 		char_height = image->/*height*/h;
976 	}
977 	char_x_left = obj_x / 2 + 58;
978 	if (Char.direction >= dir_0_right) {
979 		char_x_left -= char_width_half;
980 	}
981 	char_x_left_coll = char_x_left;
982 	char_x_right_coll = char_x_right = char_x_left + char_width_half;
983 	char_top_y = obj_y - char_height + 1;
984 	if (char_top_y >= 192) {
985 		char_top_y = 0;
986 	}
987 	char_top_row = y_to_row_mod4(char_top_y);
988 	char_bottom_row = y_to_row_mod4(obj_y);
989 	if (char_bottom_row == -1) {
990 		char_bottom_row = 3;
991 	}
992 	char_col_left = MAX(get_tile_div_mod(char_x_left), 0);
993 	char_col_right = MIN(get_tile_div_mod(char_x_right), 9);
994 	if (cur_frame.flags & FRAME_THIN) {
995 		// "thin" this frame for collision detection
996 		char_x_left_coll += 4;
997 		char_x_right_coll -= 4;
998 	}
999 }
1000 
1001 // seg006:0815
check_on_floor()1002 void __pascal far check_on_floor() {
1003 	if (cur_frame.flags & FRAME_NEEDS_FLOOR) {
1004 		if (get_tile_at_char() == tiles_20_wall) {
1005 			in_wall();
1006 		}
1007 		if (! tile_is_floor(curr_tile2)) {
1008 			// Special event: floors appear
1009 			if (current_level == 12 &&
1010 #ifndef FIX_HIDDEN_FLOORS_DURING_FLASHING
1011 				united_with_shadow < 0 &&
1012 #else
1013 				(united_with_shadow < 0 || (fixes->fix_hidden_floors_during_flashing && united_with_shadow > 0)) &&
1014 #endif
1015 				Char.curr_row == 0 &&
1016 				(Char.room == 2 || (Char.room == 13 && tile_col >= 6))
1017 			) {
1018 				curr_room_tiles[curr_tilepos] = tiles_1_floor;
1019 				set_wipe(curr_tilepos, 1);
1020 				set_redraw_full(curr_tilepos, 1);
1021 				++curr_tilepos;
1022 				set_wipe(curr_tilepos, 1);
1023 				set_redraw_full(curr_tilepos, 1);
1024 			} else {
1025 
1026 #ifdef FIX_STAND_ON_THIN_AIR
1027 				if (fixes->fix_stand_on_thin_air &&
1028 					Char.frame >= frame_110_stand_up_from_crouch_1 && Char.frame <= frame_119_stand_up_from_crouch_10)
1029 				{
1030 					// We need to prevent the Kid from stepping off a ledge accidentally while standing up.
1031 					// (This can happen because the "standing up" frames now require a floor.)
1032 					// --> Cancel the fall, if the tile at dx=2 behind the kid is a valid floor.
1033 					int col = get_tile_div_mod_m7(dx_weight() + back_delta_x(2));
1034 					if (tile_is_floor(get_tile(Char.room, col, Char.curr_row))) {
1035 						return;
1036 					}
1037 				}
1038 #endif
1039 
1040 				start_fall();
1041 			}
1042 		}
1043 	}
1044 }
1045 
1046 // seg006:08B9
start_fall()1047 void __pascal far start_fall() {
1048 	short frame;
1049 	word seq_id;
1050 	frame = Char.frame;
1051 	Char.sword = sword_0_sheathed;
1052 	inc_curr_row();
1053 	start_chompers();
1054 	fall_frame = frame;
1055 	if (frame == frame_9_run) {
1056 		// frame 9: run
1057 		seq_id = seq_7_fall; // fall (when?)
1058 	} else if (frame == frame_13_run) {
1059 		// frame 13: run
1060 		seq_id = seq_19_fall; // fall (when?)
1061 	} else if (frame == frame_26_standing_jump_11) {
1062 		// frame 26: land after standing jump
1063 		seq_id = seq_18_fall_after_standing_jump; // fall after standing jump
1064 	} else if (frame == frame_44_running_jump_5) {
1065 		// frame 44: land after running jump
1066 		seq_id = seq_21_fall_after_running_jump; // fall after running jump
1067 	} else if (frame >= frame_81_hangdrop_1 && frame < 86) {
1068 		// frame 81..85: land after jump up
1069 		seq_id = seq_19_fall; // fall after jumping up
1070 		Char.x = char_dx_forward(5);
1071 		load_fram_det_col();
1072 	} else if (frame >= 150 && frame < 180) {
1073 		// frame 150..179: with sword + fall + dead
1074 		if (Char.charid == charid_2_guard) {
1075 			if (Char.curr_row == 3 && Char.curr_col == 10) {
1076 				clear_char();
1077 				return;
1078 			}
1079 			if (Char.fall_x < 0) {
1080 				seq_id = seq_82_guard_pushed_off_ledge; // Guard is pushed off the ledge
1081 				if (Char.direction < dir_0_right && distance_to_edge_weight() <= 7) {
1082 					Char.x = char_dx_forward(-5);
1083 				}
1084 			} else {
1085 				droppedout = 0;
1086 				seq_id = seq_83_guard_fall; // fall after forwarding with sword
1087 			}
1088 		} else {
1089 			droppedout = 1;
1090 			if (Char.direction < dir_0_right && distance_to_edge_weight() <= 7) {
1091 				Char.x = char_dx_forward(-5);
1092 			}
1093 			seq_id = seq_81_kid_pushed_off_ledge; // fall after backing with sword / Kid is pushed off the ledge
1094 		}
1095 	} else {
1096 		seq_id = seq_7_fall; // fall after stand, run, step, crouch
1097 	}
1098 	seqtbl_offset_char(seq_id);
1099 	play_seq();
1100 	load_fram_det_col();
1101 	if (get_tile_at_char() == tiles_20_wall) {
1102 		in_wall();
1103 		return;
1104 	}
1105 	int tile = get_tile_infrontof_char();
1106 	if (tile == tiles_20_wall
1107 
1108 		#ifdef FIX_RUNNING_JUMP_THROUGH_TAPESTRY
1109 			// Also treat tapestries (when approached to the left) like a wall here.
1110 		|| (fixes->fix_running_jump_through_tapestry && Char.direction == dir_FF_left &&
1111 			(tile == tiles_12_doortop || tile == tiles_7_doortop_with_floor))
1112 		#endif
1113 
1114 			) {
1115 		if (fall_frame != 44 || distance_to_edge_weight() >= 6) {
1116 			Char.x = char_dx_forward(-1);
1117 		} else {
1118 			seqtbl_offset_char(seq_104_start_fall_in_front_of_wall); // start fall (when?)
1119 			play_seq();
1120 		}
1121 		load_fram_det_col();
1122 	}
1123 }
1124 
1125 // seg006:0A19
check_grab()1126 void __pascal far check_grab() {
1127 	word old_x;
1128 
1129 	#ifdef FIX_GRAB_FALLING_SPEED
1130 	#define MAX_GRAB_FALLING_SPEED (fixes->fix_grab_falling_speed ? 30 : 32)
1131 	#else
1132 	#define MAX_GRAB_FALLING_SPEED 32
1133 	#endif
1134 
1135 	if (control_shift < 0 && // press Shift to grab
1136 		Char.fall_y < MAX_GRAB_FALLING_SPEED && // you can't grab if you're falling too fast ...
1137 		Char.alive < 0 && // ... or dead
1138 		(word)y_land[Char.curr_row + 1] <= (word)(Char.y + 25)
1139 	) {
1140 		//printf("Falling speed: %d\t x: %d\n", Char.fall_y, Char.x);
1141 		old_x = Char.x;
1142 		Char.x = char_dx_forward(-8);
1143 		load_fram_det_col();
1144 		if ( ! can_grab_front_above()) {
1145 			Char.x = old_x;
1146 		} else {
1147 			Char.x = char_dx_forward(distance_to_edge_weight());
1148 			Char.y = y_land[Char.curr_row + 1];
1149 			Char.fall_y = 0;
1150 			seqtbl_offset_char(seq_15_grab_ledge_midair); // grab a ledge (after falling)
1151 			play_seq();
1152 			grab_timer = 12;
1153 			play_sound(sound_9_grab); // grab
1154 			is_screaming = 0;
1155 #ifdef FIX_CHOMPERS_NOT_STARTING
1156 			if (fixes->fix_chompers_not_starting) start_chompers();
1157 #endif
1158 		}
1159 	}
1160 }
1161 
1162 // seg006:0ABD
can_grab_front_above()1163 int __pascal far can_grab_front_above() {
1164 	through_tile = get_tile_above_char();
1165 	get_tile_front_above_char();
1166 	return can_grab();
1167 }
1168 
1169 // seg006:0ACD
in_wall()1170 void __pascal far in_wall() {
1171 	short delta_x;
1172 	delta_x = distance_to_edge_weight();
1173 	if (delta_x >= 8 || get_tile_infrontof_char() == tiles_20_wall) {
1174 		delta_x = 6 - delta_x;
1175 	} else {
1176 		delta_x += 4;
1177 	}
1178 	Char.x = char_dx_forward(delta_x);
1179 	load_fram_det_col();
1180 	get_tile_at_char();
1181 }
1182 
1183 // seg006:0B0C
get_tile_infrontof_char()1184 int __pascal far get_tile_infrontof_char() {
1185 	return get_tile(Char.room, infrontx = dir_front[Char.direction + 1] + Char.curr_col, Char.curr_row);
1186 }
1187 
1188 // seg006:0B30
get_tile_infrontof2_char()1189 int __pascal far get_tile_infrontof2_char() {
1190 	short var_2;
1191 	var_2 = dir_front[Char.direction + 1];
1192 	return get_tile(Char.room, infrontx = (var_2 << 1) + Char.curr_col, Char.curr_row);
1193 }
1194 
1195 // seg006:0B66
get_tile_behind_char()1196 int __pascal far get_tile_behind_char() {
1197 	return get_tile(Char.room, dir_behind[Char.direction + 1] + Char.curr_col, Char.curr_row);
1198 }
1199 
1200 // seg006:0B8A
distance_to_edge_weight()1201 int __pascal far distance_to_edge_weight() {
1202 	return distance_to_edge(dx_weight());
1203 }
1204 
1205 // seg006:0B94
distance_to_edge(int xpos)1206 int __pascal far distance_to_edge(int xpos) {
1207 	short distance;
1208 	get_tile_div_mod_m7(xpos);
1209 	distance = obj_xl;
1210 	if (Char.direction == dir_0_right) {
1211 		distance = 13 - distance;
1212 	}
1213 	return distance;
1214 }
1215 
1216 // seg006:0BC4
fell_out()1217 void __pascal far fell_out() {
1218 	if (Char.alive < 0 && Char.room == 0) {
1219 		take_hp(100);
1220 		Char.alive = 0;
1221 		erase_bottom_text(1);
1222 		Char.frame = frame_185_dead; // dead
1223 	}
1224 }
1225 
1226 // seg006:0BEE
play_kid()1227 void __pascal far play_kid() {
1228 	fell_out();
1229 	control_kid();
1230 	if (Char.alive >= 0 && is_dead()) {
1231 		if (resurrect_time) {
1232 			stop_sounds();
1233 			loadkid();
1234 			hitp_delta = hitp_max;
1235 			seqtbl_offset_char(seq_2_stand); // stand
1236 			Char.x += 8;
1237 			play_seq();
1238 			load_fram_det_col();
1239 			set_start_pos();
1240 		}
1241 		if (check_sound_playing() && current_sound != 5) { // gate opening
1242 			return;
1243 		}
1244 		is_show_time = 0;
1245 		if (Char.alive < 0 || Char.alive >= 6) {
1246 			if (Char.alive == 6) {
1247 				if (is_sound_on &&
1248 					current_level != 0 && // no death music on demo level
1249 					current_level != 15 // no death music on potions level
1250 				) {
1251 					play_death_music();
1252 				}
1253 			} else {
1254 				if (Char.alive != 7 || check_sound_playing()) return;
1255 				if (rem_min == 0) {
1256 					expired();
1257 				}
1258 				if (current_level != 0 && // no message if died on demo level
1259 					current_level != 15 // no message if died on potions level
1260 				) {
1261 					text_time_remaining = text_time_total = 288;
1262 					display_text_bottom("Press Button to Continue");
1263 				} else {
1264 					text_time_remaining = text_time_total = 36;
1265 				}
1266 			}
1267 		}
1268 		++Char.alive;
1269 	}
1270 }
1271 
1272 // seg006:0CD1
control_kid()1273 void __pascal far control_kid() {
1274 	word key;
1275 	if (Char.alive < 0 && hitp_curr == 0) {
1276 		Char.alive = 0;
1277 		// stop feather fall when kid dies
1278 		if (fixes->fix_quicksave_during_feather && is_feather_fall > 0) {
1279 			is_feather_fall = 0;
1280 			if (check_sound_playing()) {
1281 				stop_sounds();
1282 			}
1283 		}
1284 	}
1285 	if (grab_timer != 0) {
1286 		--grab_timer;
1287 	}
1288 #ifdef USE_REPLAY
1289 	if (current_level == 0 && !play_demo_level && !replaying) {
1290 #else
1291 	if (current_level == 0 && !play_demo_level) {
1292 #endif
1293 		do_demo();
1294 		control();
1295 		// The player can start a new game or load a saved game during the demo.
1296 		key = key_test_quit();
1297 		if (key == (SDL_SCANCODE_L | WITH_CTRL)) { // Ctrl+L
1298 			if (load_game()) {
1299 				start_game();
1300 			}
1301 		} else {
1302 			if (key) {
1303 				start_level = custom->first_level; // 1
1304 				start_game();
1305 			}
1306 		}
1307 	} else {
1308 		rest_ctrl_1();
1309 		do_paused();
1310 		#ifdef USE_REPLAY
1311 		if (recording) add_replay_move();
1312 		if (replaying) do_replay_move();
1313 		#endif
1314 		read_user_control();
1315 		user_control();
1316 		save_ctrl_1();
1317 	}
1318 }
1319 
1320 // This was moved to custom_options_type.
1321 /*
1322 const auto_move_type demo_moves[] = {
1323 {0x00, 0},
1324 {0x01, 1},
1325 {0x0D, 0},
1326 {0x1E, 1},
1327 {0x25, 5},
1328 {0x2F, 0},
1329 {0x30, 1},
1330 {0x41, 0},
1331 {0x49, 2},
1332 {0x4B, 0},
1333 {0x63, 2},
1334 {0x64, 0},
1335 {0x73, 5},
1336 {0x80, 6},
1337 {0x88, 3},
1338 {0x9D, 7},
1339 {0x9E, 0},
1340 {0x9F, 1},
1341 {0xAB, 4},
1342 {0xB1, 0},
1343 {0xB2, 1},
1344 {0xBC, 0},
1345 {0xC1, 1},
1346 {0xCD, 0},
1347 {0xE9,-1},
1348 };
1349 */
1350 
1351 // seg006:0D49
1352 void __pascal far do_demo() {
1353 	if (checkpoint) {
1354 		control_shift2 = release_arrows();
1355 		control_forward = control_x = -1;
1356 	} else if (Char.sword) {
1357 		guard_skill = 10;
1358 		autocontrol_opponent();
1359 		guard_skill = 11;
1360 	} else {
1361 		do_auto_moves(custom->demo_moves);
1362 	}
1363 }
1364 
1365 // seg006:0D85
1366 void __pascal far play_guard() {
1367 	if (Char.charid == charid_24_mouse) {
1368 		autocontrol_opponent();
1369 	} else {
1370 		if (Char.alive < 0) {
1371 			if (guardhp_curr == 0) {
1372 				Char.alive = 0;
1373 				on_guard_killed();
1374 			} else {
1375 				goto loc_7A65;
1376 			}
1377 		}
1378 		if (Char.charid == charid_1_shadow) {
1379 			clear_char();
1380 		}
1381 		loc_7A65:
1382 		autocontrol_opponent();
1383 		control();
1384 	}
1385 }
1386 
1387 // seg006:0DC0
1388 void __pascal far user_control() {
1389 	if (Char.direction >= dir_0_right) {
1390 		flip_control_x();
1391 		control();
1392 		flip_control_x();
1393 	} else {
1394 		control();
1395 	}
1396 }
1397 
1398 // seg006:0DDC
1399 void __pascal far flip_control_x() {
1400 	byte temp;
1401 	control_x = -control_x;
1402 	temp = control_forward;
1403 	control_forward = control_backward;
1404 	control_backward = temp;
1405 }
1406 
1407 // seg006:0E00
1408 int __pascal far release_arrows() {
1409 	control_backward = control_forward = control_up = control_down = 0;
1410 	return 1;
1411 }
1412 
1413 // seg006:0E12
1414 void __pascal far save_ctrl_1() {
1415 	ctrl1_forward = control_forward;
1416 	ctrl1_backward = control_backward;
1417 	ctrl1_up = control_up;
1418 	ctrl1_down = control_down;
1419 	ctrl1_shift2 = control_shift2;
1420 }
1421 
1422 // seg006:0E31
1423 void __pascal far rest_ctrl_1() {
1424 	control_forward = ctrl1_forward;
1425 	control_backward = ctrl1_backward;
1426 	control_up = ctrl1_up;
1427 	control_down = ctrl1_down;
1428 	control_shift2 = ctrl1_shift2;
1429 }
1430 
1431 // seg006:0E8E
1432 void __pascal far clear_saved_ctrl() {
1433 	ctrl1_forward = ctrl1_backward = ctrl1_up = ctrl1_down = ctrl1_shift2 = 0;
1434 }
1435 
1436 // seg006:0EAF
1437 void __pascal far read_user_control() {
1438 	if (control_forward >= 0) {
1439 		if (control_x < 0) {
1440 			if (control_forward == 0) {
1441 				control_forward = -1;
1442 			}
1443 		} else {
1444 			control_forward = 0;
1445 		}
1446 	}
1447 	if (control_backward >= 0) {
1448 		if (control_x == 1) {
1449 			if (control_backward == 0) {
1450 				control_backward = -1;
1451 			}
1452 		} else {
1453 			control_backward = 0;
1454 		}
1455 	}
1456 	if (control_up >= 0) {
1457 		if (control_y < 0) {
1458 			if (control_up == 0) {
1459 				control_up = -1;
1460 			}
1461 		} else {
1462 			control_up = 0;
1463 		}
1464 	}
1465 	if (control_down >= 0) {
1466 		if (control_y == 1) {
1467 			if (control_down == 0) {
1468 				control_down = -1;
1469 			}
1470 		} else {
1471 			control_down = 0;
1472 		}
1473 	}
1474 	if (control_shift2 >= 0) {
1475 		if (control_shift < 0) {
1476 			if (control_shift2 == 0) {
1477 				control_shift2 = -1;
1478 			}
1479 		} else {
1480 			control_shift2 = 0;
1481 		}
1482 	}
1483 }
1484 
1485 // seg006:0F55
1486 int __pascal far can_grab() {
1487 	// Can char grab curr_tile2 through through_tile?
1488 	byte modifier;
1489 	modifier = curr_room_modif[curr_tilepos];
1490 	// can't grab through wall
1491 	if (through_tile == tiles_20_wall) return 0;
1492 	// can't grab through a door top if looking right
1493 	if (through_tile == tiles_12_doortop && Char.direction >= dir_0_right) return 0;
1494 	// can't grab through floor
1495 	if (tile_is_floor(through_tile)) return 0;
1496 	// can't grab a shaking loose floor
1497 	// Allow climbing onto a shaking loose floor if the delay is greater than the default. TODO: This should be a separate option.
1498 	if (curr_tile2 == tiles_11_loose && modifier != 0 && !(custom->loose_floor_delay > 11)) return 0;
1499 	// a doortop with floor can be grabbed only from the left (looking right)
1500 	if (curr_tile2 == tiles_7_doortop_with_floor && Char.direction < dir_0_right) return 0;
1501 	// can't grab something that has no floor
1502 	if ( ! tile_is_floor(curr_tile2)) return 0;
1503 	return 1;
1504 }
1505 
1506 // seg006:0FC3
1507 int __pascal far wall_type(byte tiletype) {
1508 	switch (tiletype) {
1509 		case tiles_4_gate:
1510 		case tiles_7_doortop_with_floor:
1511 		case tiles_12_doortop:
1512 			return 1; // wall at right
1513 		case tiles_13_mirror:
1514 			return 2; // wall at left
1515 		case tiles_18_chomper:
1516 			return 3; // chomper at left
1517 		case tiles_20_wall:
1518 			return 4; // wall at both sides
1519 		default:
1520 			return 0; // no wall
1521 	}
1522 }
1523 
1524 // seg006:1005
1525 int __pascal far get_tile_above_char() {
1526 	return get_tile(Char.room, Char.curr_col, Char.curr_row - 1);
1527 }
1528 
1529 // seg006:1020
1530 int __pascal far get_tile_behind_above_char() {
1531 	return get_tile(Char.room, dir_behind[Char.direction + 1] + Char.curr_col, Char.curr_row - 1);
1532 }
1533 
1534 // seg006:1049
1535 int __pascal far get_tile_front_above_char() {
1536 	return get_tile(Char.room, infrontx = dir_front[Char.direction + 1] + Char.curr_col, Char.curr_row - 1);
1537 }
1538 
1539 // seg006:1072
1540 int __pascal far back_delta_x(int delta_x) {
1541 	if (Char.direction < dir_0_right) {
1542 		// direction = left
1543 		return delta_x;
1544 	} else {
1545 		// direction = right
1546 		return -delta_x;
1547 	}
1548 }
1549 
1550 // seg006:108A
1551 void __pascal far do_pickup(int obj_type) {
1552 	pickup_obj_type = obj_type;
1553 	control_shift2 = 1;
1554 	// erase picked up item
1555 	curr_room_tiles[curr_tilepos] = tiles_1_floor;
1556 	curr_room_modif[curr_tilepos] = 0;
1557 	redraw_height = 35;
1558 	set_wipe(curr_tilepos, 1);
1559 	set_redraw_full(curr_tilepos, 1);
1560 }
1561 
1562 // seg006:10E6
1563 void __pascal far check_press() {
1564 	short frame;
1565 	short action;
1566 	frame = Char.frame;
1567 	action = Char.action;
1568 	// frames 87..99: hanging
1569 	// frames 135..140: start climb up
1570 	if ((frame >= frame_87_hanging_1 && frame < 100) || (frame >= frame_135_climbing_1 && frame < frame_141_climbing_7)) {
1571 		// the pressed tile is the one that the char is grabbing
1572 		get_tile_above_char();
1573 	} else if (action == actions_7_turn || action == actions_5_bumped || action < actions_2_hang_climb) {
1574 		// frame 79: jumping up
1575 		if (frame == frame_79_jumphang && get_tile_above_char() == tiles_11_loose) {
1576 			// break a loose floor from above
1577 			make_loose_fall(1);
1578 		} else {
1579 			// the pressed tile is the one that the char is standing on
1580 			if (! (cur_frame.flags & FRAME_NEEDS_FLOOR)) return;
1581 			#ifdef FIX_PRESS_THROUGH_CLOSED_GATES
1582 			if (fixes->fix_press_through_closed_gates) determine_col();
1583 			#endif
1584 			get_tile_at_char();
1585 		}
1586 	} else {
1587 		return;
1588 	}
1589 	if (curr_tile2 == tiles_15_opener || curr_tile2 == tiles_6_closer) {
1590 		if (Char.alive < 0) {
1591 			trigger_button(1, 0, -1);
1592 		} else {
1593 			died_on_button();
1594 		}
1595 	} else if (curr_tile2 == tiles_11_loose) {
1596 		is_guard_notice = 1;
1597 		make_loose_fall(1);
1598 	}
1599 }
1600 
1601 // seg006:1199
1602 void __pascal far check_spike_below() {
1603 	short not_finished;
1604 	short room;
1605 	short row;
1606 	short col;
1607 	short right_col;
1608 	right_col = get_tile_div_mod_m7(char_x_right);
1609 	if (right_col < 0) return;
1610 	row = Char.curr_row;
1611 	room = Char.room;
1612 	for (col = get_tile_div_mod_m7(char_x_left); col <= right_col; ++col) {
1613 		row = Char.curr_row;
1614 		do {
1615 			not_finished = 0;
1616 			if (get_tile(room, col, row) == tiles_2_spike) {
1617 				start_anim_spike(curr_room, curr_tilepos);
1618 			} else if (
1619 				! tile_is_floor(curr_tile2) &&
1620 				curr_room != 0 &&
1621 #ifdef FIX_INFINITE_DOWN_BUG
1622 				(fixes->fix_infinite_down_bug ? (row <= 2) : (room == curr_room))
1623 #else
1624 				room == curr_room
1625 #endif
1626 			) {
1627 				++row;
1628 				not_finished = 1;
1629 			}
1630 		} while(not_finished);
1631 	}
1632 }
1633 
1634 // seg006:1231
1635 void __pascal far clip_char() {
1636 	short frame;
1637 	short room;
1638 	short action;
1639 	short col;
1640 	short var_A;
1641 	short row;
1642 	short var_E;
1643 	frame = Char.frame;
1644 	action = Char.action;
1645 	room = Char.room;
1646 	row = Char.curr_row;
1647 	reset_obj_clip();
1648 	// frames 217..228: going up the level door
1649 	if (frame >= frame_224_exit_stairs_8 && frame < 229) {
1650 		obj_clip_top = leveldoor_ybottom + 1;
1651 		obj_clip_right = leveldoor_right;
1652 	} else {
1653 		if (
1654 			get_tile(room, char_col_left, char_top_row) == tiles_20_wall ||
1655 			tile_is_floor(curr_tile2)
1656 		) {
1657 			// frame 79: jump up, frame 81: grab
1658 			if ((action == actions_0_stand && (frame == frame_79_jumphang || frame == frame_81_hangdrop_1)) ||
1659 				get_tile(room, char_col_right, char_top_row) == tiles_20_wall ||
1660 				tile_is_floor(curr_tile2)
1661 			) {
1662 				var_E = row + 1;
1663 				if (var_E == 1 ||
1664 					((var_A = y_clip[var_E]) < obj_y && var_A - 15 < char_top_y)
1665 				) {
1666 					obj_clip_top = char_top_y = y_clip[var_E];
1667 				}
1668 			}
1669 		}
1670 		col = get_tile_div_mod(char_x_left_coll - 4);
1671 		if (get_tile(room, col + 1, row) == tiles_7_doortop_with_floor ||
1672 			curr_tile2 == tiles_12_doortop
1673 		) {
1674 			obj_clip_right = (tile_col << 5) + 32;
1675 		} else {
1676 			if ((get_tile(room, col, row) != tiles_7_doortop_with_floor &&
1677 				curr_tile2 != tiles_12_doortop) ||
1678 				action == actions_3_in_midair ||
1679 				(action == actions_4_in_freefall && frame == frame_106_fall) ||
1680 				(action == actions_5_bumped && frame == frame_107_fall_land_1) ||
1681 				(Char.direction < dir_0_right && (
1682 					action == actions_2_hang_climb ||
1683 					action == actions_6_hang_straight ||
1684 					(action == actions_1_run_jump &&
1685 					frame >= frame_137_climbing_3 && frame < frame_140_climbing_6)
1686 				))
1687 			) {
1688 				if (
1689 					(get_tile(room, col = get_tile_div_mod(char_x_right_coll), row) == tiles_20_wall ||
1690 					(curr_tile2 == tiles_13_mirror && Char.direction == dir_0_right)) &&
1691 					(get_tile(room, col, char_top_row) == tiles_20_wall ||
1692 					curr_tile2 == tiles_13_mirror) &&
1693 					room == curr_room
1694 				) {
1695 					obj_clip_right = tile_col << 5;
1696 				}
1697 			} else {
1698 				obj_clip_right = (tile_col << 5) + 32;
1699 			}
1700 		}
1701 	}
1702 }
1703 
1704 // seg006:13E6
1705 void __pascal far stuck_lower() {
1706 	if (get_tile_at_char() == tiles_5_stuck) {
1707 		++Char.y;
1708 	}
1709 }
1710 
1711 // seg006:13F3
1712 void __pascal far set_objtile_at_char() {
1713 	short char_frame;
1714 	short char_action;
1715 	char_frame = Char.frame;
1716 	char_action = Char.action;
1717 	if (char_action == actions_1_run_jump) {
1718 		tile_row = char_bottom_row;
1719 		tile_col = char_col_left;
1720 	} else {
1721 		tile_row = Char.curr_row;
1722 		tile_col = Char.curr_col;
1723 	}
1724 	// frame 135..148: climbing
1725 	if ((char_frame >= frame_135_climbing_1 && char_frame < 149) ||
1726 		char_action == actions_2_hang_climb ||
1727 		char_action == actions_3_in_midair ||
1728 		char_action == actions_4_in_freefall ||
1729 		char_action == actions_6_hang_straight
1730 	) {
1731 		--tile_col;
1732 	}
1733 	obj_tilepos = get_tilepos_nominus(tile_col, tile_row);
1734 	//printf("set_objtile_at_char: obj_tile = %d\n", obj_tile); // debug
1735 }
1736 
1737 // seg006:1463
1738 void __pascal far proc_get_object() {
1739 	if (Char.charid != charid_0_kid || pickup_obj_type == 0) return;
1740 	if (pickup_obj_type == -1) {
1741 		have_sword = -1;
1742 		play_sound(sound_37_victory); // get sword
1743 		flash_color = color_14_brightyellow;
1744 		flash_time = 8;
1745 	} else {
1746 		switch (--pickup_obj_type) {
1747 			case 0: // health
1748 				if (hitp_curr != hitp_max) {
1749 					stop_sounds();
1750 					play_sound(sound_33_small_potion); // small potion
1751 					hitp_delta = 1;
1752 					flash_color = color_4_red;
1753 					flash_time = 2;
1754 				}
1755 			break;
1756 			case 1: // life
1757 				stop_sounds();
1758 				play_sound(sound_30_big_potion); // big potion
1759 				flash_color = color_4_red;
1760 				flash_time = 4;
1761 				add_life();
1762 			break;
1763 			case 2: // feather
1764 				feather_fall();
1765 			break;
1766 			case 3: // invert
1767 				toggle_upside();
1768 			break;
1769 			case 5: // open
1770 				get_tile(8, 0, 0);
1771 				trigger_button(0, 0, -1);
1772 			break;
1773 			case 4: // hurt
1774 				stop_sounds();
1775 				play_sound(sound_13_kid_hurt); // Kid hurt (by potion)
1776 				// Special event: blue potions on potions level take half of HP
1777 				if (current_level == 15) {
1778 					hitp_delta = - ((hitp_max + 1) >> 1);
1779 				} else {
1780 					hitp_delta = -1;
1781 				}
1782 			break;
1783 		}
1784 	}
1785 }
1786 
1787 // seg006:1599
1788 int __pascal far is_dead() {
1789 	// 177: spiked, 178: chomped, 185: dead
1790 	// or maybe this was a switch-case?
1791 	return Char.frame >= frame_177_spiked && (Char.frame <= frame_178_chomped || Char.frame == frame_185_dead);
1792 }
1793 
1794 // seg006:15B5
1795 void __pascal far play_death_music() {
1796 	word sound_id;
1797 	if (Guard.charid == charid_1_shadow) {
1798 		sound_id = sound_32_shadow_music; // killed by shadow
1799 	} else if (holding_sword) {
1800 		sound_id = sound_28_death_in_fight; // death in fight
1801 	} else {
1802 		sound_id = sound_24_death_regular; // death not in fight
1803 	}
1804 	play_sound(sound_id);
1805 }
1806 
1807 // seg006:15E8
1808 void __pascal far on_guard_killed() {
1809 	if (current_level == 0) {
1810 		// demo level: after killing Guard, run out of room
1811 		checkpoint = 1;
1812 		demo_index = demo_time = 0;
1813 	} else if (current_level == /*13*/ custom->jaffar_victory_level) {
1814 		// Jaffar's level: flash
1815 		flash_color = color_15_brightwhite; // white
1816 		flash_time = /*18*/ custom->jaffar_victory_flash_time;
1817 		is_show_time = 1;
1818 		leveldoor_open = 2;
1819 		play_sound(sound_43_victory_Jaffar); // Jaffar's death
1820 	} else if (Char.charid != charid_1_shadow) {
1821 		play_sound(sound_37_victory); // Guard's death
1822 	}
1823 }
1824 
1825 // seg006:1634
1826 void __pascal far clear_char() {
1827 	Char.direction = dir_56_none;
1828 	Char.alive = 0;
1829 	Char.action = 0;
1830 	draw_guard_hp(0, guardhp_curr);
1831 	guardhp_curr = 0;
1832 }
1833 
1834 // data:42EC
1835 byte obj2_tilepos;
1836 // data:34A6
1837 word obj2_x;
1838 // data:34A8
1839 byte obj2_y;
1840 // data:599E
1841 sbyte obj2_direction;
1842 // data:5948
1843 byte obj2_id;
1844 // data:42BE
1845 byte obj2_chtab;
1846 // data:4D90
1847 short obj2_clip_top;
1848 // data:460C
1849 short obj2_clip_bottom;
1850 // data:4C94
1851 short obj2_clip_left;
1852 // data:4CDE
1853 short obj2_clip_right;
1854 
1855 // seg006:1654
1856 void __pascal far save_obj() {
1857 	obj2_tilepos = obj_tilepos;
1858 	obj2_x = obj_x;
1859 	obj2_y = obj_y;
1860 	obj2_direction = obj_direction;
1861 	obj2_id = obj_id;
1862 	obj2_chtab = obj_chtab;
1863 	obj2_clip_top = obj_clip_top;
1864 	obj2_clip_bottom = obj_clip_bottom;
1865 	obj2_clip_left = obj_clip_left;
1866 	obj2_clip_right = obj_clip_right;
1867 }
1868 
1869 // seg006:1691
1870 void __pascal far load_obj() {
1871 	obj_tilepos = obj2_tilepos;
1872 	obj_x = obj2_x;
1873 	obj_y = obj2_y;
1874 	obj_direction = obj2_direction;
1875 	obj_id = obj2_id;
1876 	obj_chtab = obj2_chtab;
1877 	obj_clip_top = obj2_clip_top;
1878 	obj_clip_bottom = obj2_clip_bottom;
1879 	obj_clip_left = obj2_clip_left;
1880 	obj_clip_right = obj2_clip_right;
1881 }
1882 
1883 // seg006:16CE
1884 void __pascal far draw_hurt_splash() {
1885 	short frame;
1886 	frame = Char.frame;
1887 	if (frame != frame_178_chomped) { // chomped
1888 		save_obj();
1889 		obj_tilepos = -1;
1890 		// frame 185: dead
1891 		// frame 106..110: fall + land
1892 		if (frame == frame_185_dead || (frame>= frame_106_fall && frame<111)) {
1893 			obj_y += 4;
1894 			obj_dx_forward(5);
1895 		} else if (frame == frame_177_spiked) { // spiked
1896 			obj_dx_forward(-5);
1897 		} else {
1898 			obj_y -= ((Char.charid == charid_0_kid) << 2) + 11;
1899 			obj_dx_forward(5);
1900 		}
1901 		if (Char.charid == charid_0_kid) {
1902 			obj_chtab = id_chtab_2_kid;
1903 			obj_id = 218; // splash!
1904 		} else {
1905 			obj_chtab = id_chtab_5_guard;
1906 			obj_id = 1; // splash!
1907 		}
1908 		reset_obj_clip();
1909 		add_objtable(5); // hurt splash
1910 		load_obj();
1911 	}
1912 }
1913 
1914 // seg006:175D
1915 void __pascal far check_killed_shadow() {
1916 	// Special event: killed the shadow
1917 	if (current_level == 12) {
1918 		if ((Char.charid | Opp.charid) == charid_1_shadow &&
1919 			Char.alive < 0 && Opp.alive >= 0
1920 		) {
1921 			flash_color = color_15_brightwhite; // white
1922 			flash_time = 5;
1923 			take_hp(100);
1924 		}
1925 	}
1926 }
1927 
1928 // data:1712
1929 const sword_table_type sword_tbl[] = {
1930 { 255,   0,   0},
1931 {   0,   0,  -9},
1932 {   5,  -9, -29},
1933 {   1,   7, -25},
1934 {   2,  17, -26},
1935 {   6,   7, -14},
1936 {   7,   0,  -5},
1937 {   3,  17, -16},
1938 {   4,  16, -19},
1939 {  30,  12,  -9},
1940 {   8,  13, -34},
1941 {   9,   7, -25},
1942 {  10,  10, -16},
1943 {  11,  10, -11},
1944 {  12,  22, -21},
1945 {  13,  28, -23},
1946 {  14,  13, -35},
1947 {  15,   0, -38},
1948 {  16,   0, -29},
1949 {  17,  21, -19},
1950 {  18,  14, -23},
1951 {  19,  21, -22},
1952 {  19,  22, -23},
1953 {  17,   7, -13},
1954 {  17,  15, -18},
1955 {   7,   0,  -8},
1956 {   1,   7, -27},
1957 {  28,  14, -28},
1958 {   8,   7, -27},
1959 {   4,   6, -23},
1960 {   4,   9, -21},
1961 {  10,  11, -18},
1962 {  13,  24, -23},
1963 {  13,  19, -23},
1964 {  13,  21, -23},
1965 {  20,   7, -32},
1966 {  21,  14, -32},
1967 {  22,  14, -31},
1968 {  23,  14, -29},
1969 {  24,  28, -28},
1970 {  25,  28, -28},
1971 {  26,  21, -25},
1972 {  27,  14, -22},
1973 { 255,  14, -25},
1974 { 255,  21, -25},
1975 {  29,   0, -16},
1976 {   8,   8, -37},
1977 {  31,  14, -24},
1978 {  32,  14, -24},
1979 {  33,   7, -14},
1980 {   8,   8, -37},
1981 };
1982 
1983 // seg006:1798
1984 void __pascal far add_sword_to_objtable() {
1985 	short frame;
1986 	short sword_frame;
1987 	frame = Char.frame;
1988 	if ((frame >= frame_229_found_sword && frame < 238) || // found sword + put sword away
1989 		Char.sword != sword_0_sheathed ||
1990 		(Char.charid == charid_2_guard && Char.alive < 0)
1991 	) {
1992 		sword_frame = cur_frame.sword & 0x3F;
1993 		if (sword_frame) {
1994 			obj_id = sword_tbl[sword_frame].id;
1995 			if (obj_id != 0xFF) {
1996 				obj_x = calc_screen_x_coord(obj_x);
1997 				obj_dx_forward(sword_tbl[sword_frame].x);
1998 				obj_y += sword_tbl[sword_frame].y;
1999 				obj_chtab = id_chtab_0_sword;
2000 				add_objtable(3); // sword
2001 			}
2002 		}
2003 	}
2004 }
2005 
2006 // seg006:1827
2007 void __pascal far control_guard_inactive() {
2008 	if (Char.frame == frame_166_stand_inactive && control_down < 0) {
2009 		if (control_forward < 0) {
2010 			draw_sword();
2011 		} else {
2012 			control_down = 1;
2013 			seqtbl_offset_char(seq_80_stand_flipped); // stand flipped
2014 		}
2015 	}
2016 }
2017 
2018 // seg006:1852
2019 int __pascal far char_opp_dist() {
2020 	// >0 if Opp is in front of char
2021 	// <0 if Opp is behind char
2022 	short distance;
2023 	if (Char.room != Opp.room) {
2024 		return 999;
2025 	}
2026 	distance = Opp.x - Char.x;
2027 	if (Char.direction < dir_0_right) {
2028 		distance = -distance;
2029 	}
2030 	if (distance >= 0 && Char.direction != Opp.direction) {
2031 		distance += 13;
2032 	}
2033 	return distance;
2034 }
2035 
2036 // seg006:189B
2037 void __pascal far inc_curr_row() {
2038 	++Char.curr_row;
2039 }
2040