Subversion Repositories Games.Prince of Persia

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 pmbaty 1
/*
2
SDLPoP, a port/conversion of the DOS game Prince of Persia.
3
Copyright (C) 2013-2018  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 <http://www.gnu.org/licenses/>.
17
 
18
The authors of this program may be contacted at http://forum.princed.org
19
*/
20
 
21
#include "common.h"
22
 
23
// data:27E0
24
add_table_type ptr_add_table = add_backtable;
25
 
26
// data:259C
27
const piece tile_table[31] = {
28
{   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0}, // 0x00 empty
29
{  41,   1,   0,  42,   1,   2, 145,   0,  43,   0,   0,   0}, // 0x01 floor
30
{ 127,   1,   0, 133,   1,   2, 145,   0,  43,   0,   0,   0}, // 0x02 spike
31
{  92,   1,   0,  93,   1,   2,   0,  94,  43,  95,   1,   0}, // 0x03 pillar
32
{  46,   1,   0,  47,   1,   2,   0,  48,  43,  49,   3,   0}, // 0x04 door
33
{  41,   1,   1,  35,   1,   3, 145,   0,  36,   0,   0,   0}, // 0x05 stuck floor
34
{  41,   1,   0,  42,   1,   2, 145,   0,  96,   0,   0,   0}, // 0x06 close button
35
{  46,   1,   0,   0,   0,   2,   0,   0,  43,  49,   3,   0}, // 0x07 door top with floor
36
{  86,   1,   0,  87,   1,   2,   0,   0,  43,  88,   1,   0}, // 0x08 big pillar bottom
37
{   0,   0,   0,  89,   0,   3,   0,  90,   0,  91,   1,   3}, // 0x09 big pillar top
38
{  41,   1,   0,  42,   1,   2, 145,   0,  43,  12,   2,  -3}, // 0x0A potion
39
{   0,   1,   0,   0,   0,   0, 145,   0,   0,   0,   0,   0}, // 0x0B loose floor
40
{   0,   0,   0,   0,   0,   2,   0,   0,  85,  49,   3,   0}, // 0x0C door top
41
{  75,   1,   0,  42,   1,   2,   0,   0,  43,  77,   0,   0}, // 0x0D mirror
42
{  97,   1,   0,  98,   1,   2, 145,   0,  43, 100,   0,   0}, // 0x0E debris
43
{ 147,   1,   0,  42,   1,   1, 145,   0, 149,   0,   0,   0}, // 0x0F open button
44
{  41,   1,   0,  37,   0,   0,   0,  38,  43,   0,   0,   0}, // 0x10 leveldoor left
45
{   0,   0,   0,  39,   1,   2,   0,  40,  43,   0,   0,   0}, // 0x11 leveldoor right
46
{   0,   0,   0,  42,   1,   2, 145,   0,  43,   0,   0,   0}, // 0x12 chomper
47
{  41,   1,   0,  42,   1,   2,   0,   0,  43,   0,   0,   0}, // 0x13 torch
48
{   0,   0,   0,   1,   1,   2,   0,   2,   0,   0,   0,   0}, // 0x14 wall
49
{  30,   1,   0,  31,   1,   2,   0,   0,  43,   0,   0,   0}, // 0x15 skeleton
50
{  41,   1,   0,  42,   1,   2, 145,   0,  43,   0,   0,   0}, // 0x16 sword
51
{  41,   1,   0,  10,   0,   0,   0,  11,  43,   0,   0,   0}, // 0x17 balcony left
52
{   0,   0,   0,  12,   1,   2,   0,  13,  43,   0,   0,   0}, // 0x18 balcony right
53
{  92,   1,   0,  42,   1,   2, 145,   0,  43,  95,   1,   0}, // 0x19 lattice pillar
54
{   1,   0,   0,   0,   0,   0,   0,   0,   2,   9,   0, -53}, // 0x1A lattice down
55
{   3,   0, -10,   0,   0,   0,   0,   0,   0,   9,   0, -53}, // 0x1B lattice small
56
{   4,   0, -10,   0,   0,   0,   0,   0,   0,   9,   0, -53}, // 0x1C lattice left
57
{   5,   0, -10,   0,   0,   0,   0,   0,   0,   9,   0, -53}, // 0x1D lattice right
58
{  97,   1,   0,  98,   1,   2,   0,   0,  43, 100,   0,   0}, // 0x1E debris with torch
59
};
60
 
61
// data:4334
62
short drawn_row;
63
// data:4352
64
short draw_bottom_y;
65
// data:4326
66
short draw_main_y;
67
// data:34D0
68
short drawn_col;
69
 
70
// data:6592
71
byte tile_left;
72
// data:4CCC
73
byte modifier_left;
74
 
75
// seg008:0006
76
void __pascal far redraw_room() {
77
        free_peels();
78
        memset_near(table_counts, 0, sizeof(table_counts));
79
        reset_obj_clip();
80
        draw_room();
81
        clear_tile_wipes();
82
}
83
 
84
// seg008:0035
85
void __pascal far load_room_links() {
86
        room_BR = 0;
87
        room_BL = 0;
88
        room_AR = 0;
89
        room_AL = 0;
90
        if (drawn_room) {
91
                get_room_address(drawn_room);
92
                room_L = level.roomlinks[drawn_room-1].left;
93
                room_R = level.roomlinks[drawn_room-1].right;
94
                room_A = level.roomlinks[drawn_room-1].up;
95
                room_B = level.roomlinks[drawn_room-1].down;
96
                if (room_A) {
97
                        room_AL = level.roomlinks[room_A-1].left;
98
                        room_AR = level.roomlinks[room_A-1].right;
99
                } else {
100
                        if (room_L) {
101
                                room_AL = level.roomlinks[room_L-1].up;
102
                        }
103
                        if (room_R) {
104
                                room_AR = level.roomlinks[room_R-1].up;
105
                        }
106
                }
107
                if (room_B) {
108
                        room_BL = level.roomlinks[room_B-1].left;
109
                        room_BR = level.roomlinks[room_B-1].right;
110
                } else {
111
                        if (room_L) {
112
                                room_BL = level.roomlinks[room_L-1].down;
113
                        }
114
                        if (room_R) {
115
                                room_BR = level.roomlinks[room_R-1].down;
116
                        }
117
                }
118
        } else {
119
                room_B = 0;
120
                room_A = 0;
121
                room_R = 0;
122
                room_L = 0;
123
        }
124
}
125
 
126
// seg008:0125
127
void __pascal far draw_room() {
128
        word saved_room;
129
        load_leftroom();
130
        for (drawn_row = 3; drawn_row--; ) { /*2,1,0*/
131
                load_rowbelow();
132
                draw_bottom_y = 63 * drawn_row + 65;
133
                draw_main_y = draw_bottom_y - 3;
134
                for (drawn_col = 0; drawn_col < 10; drawn_col++) {
135
                        load_curr_and_left_tile();
136
                        draw_tile();
137
                }
138
        }
139
        saved_room = drawn_room;
140
        drawn_room = room_A;
141
        load_room_links();
142
        load_leftroom();
143
        drawn_row = 2;
144
        load_rowbelow();
145
        for (drawn_col = 0; drawn_col < 10; ++drawn_col) {
146
                load_curr_and_left_tile();
147
                draw_main_y = -1;
148
                draw_bottom_y = 2;
149
                draw_tile_aboveroom();
150
        }
151
        drawn_room = saved_room;
152
        load_room_links();
153
}
154
 
155
// seg008:01C7
156
void __pascal far draw_tile() {
157
        draw_tile_floorright();
158
        draw_tile_anim_topright();
159
        draw_tile_right();
160
        draw_tile_anim_right();
161
        draw_tile_bottom(0);
162
        draw_loose(0);
163
        draw_tile_base();
164
        draw_tile_anim();
165
        draw_tile_fore();
166
}
167
 
168
// seg008:01F2
169
void __pascal far draw_tile_aboveroom() {
170
        draw_tile_floorright();
171
        draw_tile_anim_topright();
172
        draw_tile_right();
173
        draw_tile_bottom(0);
174
        draw_loose(0);
175
        draw_tile_fore();
176
}
177
 
178
// seg008:0211
179
void __pascal far redraw_needed(short tilepos) {
180
        if (wipe_frames[tilepos]) {
181
                --wipe_frames[tilepos];
182
                draw_tile_wipe(wipe_heights[tilepos]);
183
        }
184
        if (redraw_frames_full[tilepos]) {
185
                --redraw_frames_full[tilepos];
186
                draw_tile();
187
        } else {
188
                if (redraw_frames_anim[tilepos]) {
189
                        --redraw_frames_anim[tilepos];
190
                        draw_tile_anim_topright();
191
                        draw_tile_anim_right();
192
                        draw_tile_anim();
193
                }
194
        }
195
        if (redraw_frames2[tilepos]) {
196
                --redraw_frames2[tilepos];
197
                draw_other_overlay();
198
        } else {
199
                if (redraw_frames_floor_overlay[tilepos]) {
200
                        --redraw_frames_floor_overlay[tilepos];
201
                        draw_floor_overlay();
202
                }
203
        }
204
        if (tile_object_redraw[tilepos]) {
205
                if (tile_object_redraw[tilepos] == 0xFF) {
206
                        draw_objtable_items_at_tile(tilepos - 1);
207
                }
208
                draw_objtable_items_at_tile(tilepos);
209
                tile_object_redraw[tilepos] = 0;
210
        }
211
        if (redraw_frames_fore[tilepos]) {
212
                --redraw_frames_fore[tilepos];
213
                draw_tile_fore();
214
        }
215
}
216
 
217
// seg008:02C1
218
void __pascal far redraw_needed_above(int column) {
219
        if (redraw_frames_above[column] != 0) {
220
                --redraw_frames_above[column];
221
                draw_tile_wipe(3);
222
                draw_tile_floorright();
223
                draw_tile_anim_topright();
224
                draw_tile_right();
225
                draw_tile_bottom(1);
226
                draw_loose(1);
227
                draw_tile_fore();
228
        }
229
}
230
 
231
// seg008:02FE
232
int __pascal far get_tile_to_draw(int room, int column, int row, byte *ptr_tiletype, byte *ptr_modifier, byte tile_room0) {
233
        word tilepos = tbl_line[row] + column;
234
        if (column == -1) {
235
                *ptr_tiletype = leftroom_[row].tiletype;
236
                *ptr_modifier = leftroom_[row].modifier;
237
        } else if (room) {
238
                *ptr_tiletype = curr_room_tiles[tilepos] & 0x1F;
239
                *ptr_modifier = curr_room_modif[tilepos];
240
        } else {
241
                *ptr_modifier = 0;
242
                *ptr_tiletype = tile_room0;
243
        }
244
        // Is this a pressed button?
245
        byte tiletype = (*ptr_tiletype) & 0x1F;
246
        byte modifier = *ptr_modifier;
247
        if (tiletype == tiles_6_closer) {
248
                if (get_doorlink_timer(modifier) > 1) {
249
                        *ptr_tiletype = tiles_5_stuck;
250
                }
251
        } else if (tiletype == tiles_15_opener) {
252
                if (get_doorlink_timer(modifier) > 1) {
253
                        *ptr_modifier = 0;
254
                        *ptr_tiletype = tiles_1_floor;
255
                }
256
        }
257
#ifdef USE_FAKE_TILES
258
        else if (tiletype == tiles_0_empty) {
259
                if (modifier == 4 || modifier == 12) {     // display a fake floor
260
                        *ptr_tiletype = tiles_1_floor;
261
                        *ptr_modifier = (modifier == 12) ? 1 : 0; // 12: noblue option
262
                }
263
                else if (modifier == 5 || modifier == 13) {   // display a fake wall
264
                        *ptr_tiletype = tiles_20_wall;
265
                        *ptr_modifier = (modifier == 13) ? 0x80 : 0; // 13: noblue option
266
                }
267
                else if (modifier == 50) {   // display a fake wall (pattern: no walls left or right)
268
                        *ptr_tiletype = tiles_20_wall;
269
                        *ptr_modifier = 0;
270
                }
271
                else if (modifier == 51) {   // display a fake wall (pattern: wall only to the right)
272
                        *ptr_tiletype = tiles_20_wall;
273
                        *ptr_modifier = 1;
274
                }
275
                else if (modifier == 52) {   // display a fake wall (pattern: wall only to the left)
276
                        *ptr_tiletype = tiles_20_wall;
277
                        *ptr_modifier = 2;
278
                }
279
                else if (modifier == 53) {   // display a fake wall (pattern: wall on both sides)
280
                        *ptr_tiletype = tiles_20_wall;
281
                        *ptr_modifier = 3;
282
                }
283
        }
284
        else if (tiletype == tiles_1_floor) {
285
                if (modifier == 6 || modifier == 14) {   // display nothing (invisible floor)
286
                        *ptr_tiletype = tiles_0_empty;
287
                        *ptr_modifier = (modifier == 14) ? 1 : 0; // modifier should be '0' for noblue, instead of '1'
288
                }
289
                else if (modifier == 5 || modifier == 13) {   // display a fake wall
290
                        *ptr_tiletype = tiles_20_wall;
291
                        *ptr_modifier = (modifier == 13) ? 0x80 : 0; // 13: noblue option
292
                }
293
                else if (modifier == 50) {   // display a fake wall (pattern: no walls left or right (noblue))
294
                        *ptr_tiletype = tiles_20_wall;
295
                        *ptr_modifier = 0;
296
                }
297
                else if (modifier == 51) {   // display a fake wall (pattern: wall only to the right)
298
                        *ptr_tiletype = tiles_20_wall;
299
                        *ptr_modifier = 1;
300
                }
301
                else if (modifier == 52) {   // display a fake wall (pattern: wall only to the left)
302
                        *ptr_tiletype = tiles_20_wall;
303
                        *ptr_modifier = 2;
304
                }
305
                else if (modifier == 53) {   // display a fake wall (pattern: wall on both sides)
306
                        *ptr_tiletype = tiles_20_wall;
307
                        *ptr_modifier = 3;
308
                }
309
        }
310
        else if (tiletype == tiles_20_wall) {
311
                // Walls are a bit strange, because a lot of modifier information is discarded in load_alter_mod() (seg008.c)
312
                // Also, the "noblue" info for the wall tile is moved to the --most significant-- modifier bit there.
313
 
314
                // load_alter_mod() has been tweaked to retain more information (now stored in the most significant 4 bytes)
315
                // Modifiers 2-7 are now accessible to define various fake tiles
316
                // Modifiers 9-15 'loop back' onto 2-7 (identical tiles), EXCEPT they also have the "noblue" bit set
317
                if (((modifier >> 4) & 7) == 4) {     // display a floor (invisible wall)
318
                        *ptr_tiletype = tiles_1_floor;
319
                        *ptr_modifier = (modifier >> 7); // modifier should be '1' for noblue option
320
                }
321
                else if (((modifier >> 4) & 7) == 6) {   // display empty tile (invisible wall)
322
                        *ptr_tiletype = tiles_0_empty;
323
                        *ptr_modifier = (modifier >> 7) ? 1 : 0; // modifier should be '0' for noblue, instead of '1'
324
                }
325
        }
326
#endif
327
#ifdef FIX_LOOSE_LEFT_OF_POTION
328
        else if (fix_loose_left_of_potion && tiletype == tiles_11_loose) {
329
                if ((*ptr_modifier & 0x7F) == 0) {
330
                        *ptr_tiletype = tiles_1_floor;
331
                }
332
        }
333
#endif
334
        return *ptr_tiletype;
335
}
336
 
337
// data:24C6
338
const word col_xh[] = {0, 4, 8, 12, 16, 20, 24, 28, 32, 36};
339
// seg008:03BB
340
void __pascal far load_curr_and_left_tile() {
341
        word tiletype;
342
        tiletype = tiles_20_wall;
343
        if (drawn_row == 2) {
344
                tiletype = drawn_tile_top_level_edge; // floor at top of level (default: tiles_1_floor)
345
        }
346
        get_tile_to_draw(drawn_room, drawn_col, drawn_row, &curr_tile, &curr_modifier, tiletype);
347
        get_tile_to_draw(drawn_room, drawn_col - 1, drawn_row, &tile_left, &modifier_left, tiletype);
348
        draw_xh = col_xh[drawn_col];
349
}
350
 
351
// seg008:041A
352
void __pascal far load_leftroom() {
353
        word row;
354
        get_room_address(room_L);
355
        for (row = 0; row < 3; ++row) {
356
                // wall at left of level (drawn_tile_left_level_edge), default: tiles_20_wall
357
                get_tile_to_draw(room_L, 9, row, &leftroom_[row].tiletype, &leftroom_[row].modifier, drawn_tile_left_level_edge);
358
        }
359
}
360
 
361
// seg008:0460
362
void __pascal far load_rowbelow() {
363
        word row_below;
364
        word column;
365
        word room;
366
        word room_left;
367
        if (drawn_row == 2) {
368
                room = room_B;
369
                room_left = room_BL;
370
                row_below = 0;
371
        } else {
372
                room = drawn_room;
373
                room_left = room_L;
374
                row_below = drawn_row + 1;
375
        }
376
        get_room_address(room);
377
        for (column = 1; column < 10; ++column) {
378
                get_tile_to_draw(room, column - 1, row_below, &row_below_left_[column].tiletype, &row_below_left_[column].modifier, tiles_0_empty);
379
        }
380
        get_room_address(room_left);
381
        // wall at left of level
382
        get_tile_to_draw(room_left, 9, row_below, &row_below_left_[0].tiletype, &row_below_left_[0].modifier, tiles_20_wall);
383
        get_room_address(drawn_room);
384
}
385
 
386
// seg008:04FA
387
void __pascal far draw_tile_floorright() {
388
        if (can_see_bottomleft() == 0) return;
389
        draw_tile_topright();
390
        if (tile_table[tile_left].floor_right == 0) return;
391
        add_backtable(id_chtab_6_environment, 42 /*floor right part*/, draw_xh, 0, tile_table[tiles_1_floor].right_y + draw_main_y, blitters_9_black, 1);
392
}
393
 
394
// seg008:053A
395
int __pascal far can_see_bottomleft() {
396
        return curr_tile == tiles_0_empty ||
397
                curr_tile == tiles_9_bigpillar_top ||
398
                curr_tile == tiles_12_doortop ||
399
                curr_tile == tiles_26_lattice_down;
400
}
401
 
402
const byte doortop_fram_top[] = {0, 81, 83, 0};
403
 
404
// seg008:055A
405
void __pascal far draw_tile_topright() {
406
        byte tiletype;
407
        tiletype = row_below_left_[drawn_col].tiletype;
408
        if (tiletype == tiles_7_doortop_with_floor || tiletype == tiles_12_doortop) {
409
                if (tbl_level_type[current_level] == 0) return;
410
                add_backtable(id_chtab_6_environment, doortop_fram_top[row_below_left_[drawn_col].modifier], draw_xh, 0, draw_bottom_y, blitters_2_or, 0);
411
        } else if (tiletype == tiles_20_wall) {
412
                add_backtable(id_chtab_7_environmentwall, 2, draw_xh, 0, draw_bottom_y, blitters_2_or, 0);
413
        } else {
414
                add_backtable(id_chtab_6_environment, tile_table[tiletype].topright_id, draw_xh, 0, draw_bottom_y, blitters_2_or, 0);
415
        }
416
}
417
 
418
const byte door_fram_top[] = {60, 61, 62, 63, 64, 65, 66, 67};
419
 
420
// seg008:05D1
421
void __pascal far draw_tile_anim_topright() {
422
        word modifier;
423
        if (    (curr_tile == tiles_0_empty ||
424
                curr_tile == tiles_9_bigpillar_top ||
425
                curr_tile == tiles_12_doortop)
426
                && row_below_left_[drawn_col].tiletype == tiles_4_gate
427
        ) {
428
                add_backtable(id_chtab_6_environment, 68 /*gate top mask*/, draw_xh, 0, draw_bottom_y, blitters_40h_mono, 0);
429
                modifier = row_below_left_[drawn_col].modifier;
430
                if (modifier > 188) modifier = 188;
431
                add_backtable(id_chtab_6_environment, door_fram_top[(modifier>>2) % 8], draw_xh, 0, draw_bottom_y, blitters_2_or, 0);
432
        }
433
}
434
 
435
const byte blueline_fram1[] = {0, 124, 125, 126};
436
const sbyte blueline_fram_y[] = {0, -20, -20, 0};
437
const byte blueline_fram3[] = {44, 44, 45, 45};
438
const byte doortop_fram_bot[] = {78, 80, 82, 0};
439
 
440
// seg008:066A
441
void __pascal far draw_tile_right() {
442
        byte id;
443
        byte blit;
444
        byte var_2;
445
        if (curr_tile == tiles_20_wall) return;
446
        switch (tile_left) {
447
                default:
448
                        id = tile_table[tile_left].right_id;
449
                        if (id) {
450
                                if (tile_left == tiles_5_stuck) {
451
                                        blit = blitters_10h_transp;
452
                                        if (curr_tile == tiles_0_empty || curr_tile == tiles_5_stuck) {
453
                                                id = 42; /*floor B*/
454
                                        }
455
                                } else {
456
                                        blit = blitters_2_or;
457
                                }
458
                                add_backtable(id_chtab_6_environment, id, draw_xh, 0, tile_table[tile_left].right_y + draw_main_y, blit, 0);
459
                        }
460
                        if (tbl_level_type[current_level] != 0) {
461
                                add_backtable(id_chtab_6_environment, tile_table[tile_left].stripe_id, draw_xh, 0, draw_main_y - 27, blitters_2_or, 0);
462
                        }
463
                        if (tile_left == tiles_19_torch || tile_left == tiles_30_torch_with_debris) {
464
                                add_backtable(id_chtab_6_environment, 146 /*torch base*/, draw_xh, 0, draw_bottom_y - 28, blitters_0_no_transp, 0);
465
                        }
466
                        break;
467
                case tiles_0_empty:
468
                        if (modifier_left > 3) return;
469
                        add_backtable(id_chtab_6_environment, blueline_fram1[modifier_left], draw_xh, 0, blueline_fram_y[modifier_left] + draw_main_y, blitters_2_or, 0);
470
                        break;
471
                case tiles_1_floor:
472
                        ptr_add_table(id_chtab_6_environment, 42 /*floor B*/, draw_xh, 0, tile_table[tile_left].right_y + draw_main_y, blitters_10h_transp, 0);
473
                        var_2 = modifier_left;
474
                        if (var_2 > 3) var_2 = 0;
475
                        if (var_2 == !!tbl_level_type[current_level]) return;
476
                        add_backtable(id_chtab_6_environment, blueline_fram3[var_2], draw_xh, 0, draw_main_y - 20, blitters_0_no_transp, 0);
477
                        break;
478
                case tiles_7_doortop_with_floor:
479
                case tiles_12_doortop:
480
                        if (tbl_level_type[current_level] == 0) return;
481
                        add_backtable(id_chtab_6_environment, doortop_fram_bot[modifier_left], draw_xh, 0, tile_table[tile_left].right_y + draw_main_y, blitters_2_or, 0);
482
                        break;
483
                case tiles_20_wall:
484
                        if (tbl_level_type[current_level] && (modifier_left & 0x80) == 0) {
485
                                add_backtable(id_chtab_6_environment, 84 /*wall stripe*/, draw_xh + 3, 0, draw_main_y - 27, blitters_0_no_transp, 0);
486
                        }
487
                        add_backtable(id_chtab_7_environmentwall, 1, draw_xh, 0, tile_table[tile_left].right_y + draw_main_y, blitters_2_or, 0);
488
                        break;
489
        }
490
}
491
 
492
const byte spikes_fram_right[] = {0, 134, 135, 136, 137, 138, 137, 135, 134, 0};
493
const byte loose_fram_right[] = {42, 71, 42, 72, 72, 42, 42, 42, 72, 72, 72, 0};
494
 
495
// seg008:08A0
496
int __pascal far get_spike_frame(byte modifier) {
497
        if (modifier & 0x80) {
498
                return 5;
499
        } else {
500
                return modifier;
501
        }
502
}
503
 
504
// seg008:08B5
505
void __pascal far draw_tile_anim_right() {
506
        switch (tile_left) {
507
                case tiles_2_spike:
508
                        add_backtable(id_chtab_6_environment, spikes_fram_right[get_spike_frame(modifier_left)], draw_xh, 0, draw_main_y - 7, blitters_10h_transp, 0);
509
                break;
510
                case tiles_4_gate:
511
                        draw_gate_back();
512
                break;
513
                case tiles_11_loose:
514
                        add_backtable(id_chtab_6_environment, loose_fram_right[get_loose_frame(modifier_left)], draw_xh, 0, draw_bottom_y - 1, blitters_2_or, 0);
515
                break;
516
                case tiles_16_level_door_left:
517
                        draw_leveldoor();
518
                break;
519
                case tiles_19_torch:
520
                case tiles_30_torch_with_debris:
521
                        if (modifier_left < 9) {
522
                                // images 1..9 are the flames
523
                                add_backtable(id_chtab_1_flameswordpotion, modifier_left + 1, draw_xh + 1, 0, draw_main_y - 40, blitters_0_no_transp, 0);
524
                        }
525
                break;
526
        }
527
}
528
 
529
const byte wall_fram_bottom[] = {7, 9, 5, 3};
530
 
531
// seg008:0971
532
void __pascal far draw_tile_bottom(word arg_0) {
533
        word chtab_id;
534
        byte id;
535
        byte blit;
536
        id = 0;
537
        blit = blitters_0_no_transp;
538
        chtab_id = id_chtab_6_environment;
539
        switch (curr_tile) {
540
                case tiles_20_wall:
541
                        if (tbl_level_type[current_level] == 0 || enable_wda_in_palace || graphics_mode != gmMcgaVga) {
542
                                id = wall_fram_bottom[curr_modifier & 0x7F];
543
                        }
544
                        chtab_id = id_chtab_7_environmentwall;
545
                        break;
546
                case tiles_12_doortop:
547
                        blit = blitters_2_or;
548
                        // fallthrough!
549
                default:
550
                        id = tile_table[curr_tile].bottom_id;
551
                        break;
552
        }
553
        if (ptr_add_table(chtab_id, id, draw_xh, 0, draw_bottom_y, blit, 0) && arg_0) {
554
                add_foretable(chtab_id, id, draw_xh, 0, draw_bottom_y, blit, 0);
555
        }
556
        if (chtab_id == id_chtab_7_environmentwall && graphics_mode != gmCga && graphics_mode != gmHgaHerc) {
557
                wall_pattern(0, 0);
558
        }
559
}
560
 
561
const byte loose_fram_bottom[] = {43, 73, 43, 74, 74, 43, 43, 43, 74, 74, 74, 0};
562
 
563
// seg008:0A38
564
void __pascal far draw_loose(int arg_0) {
565
        word id;
566
        if (curr_tile == tiles_11_loose) {
567
                id = loose_fram_bottom[get_loose_frame(curr_modifier)];
568
                add_backtable(id_chtab_6_environment, id, draw_xh, 0, draw_bottom_y, blitters_0_no_transp, 0);
569
                add_foretable(id_chtab_6_environment, id, draw_xh, 0, draw_bottom_y, blitters_0_no_transp, 0);
570
        }
571
}
572
 
573
const byte loose_fram_left[] = {41, 69, 41, 70, 70, 41, 41, 41, 70, 70, 70, 0};
574
 
575
// seg008:0A8E
576
void __pascal far draw_tile_base() {
577
        word ybottom;
578
        word id;
579
        ybottom = draw_main_y;
580
        if (tile_left == tiles_26_lattice_down && curr_tile == tiles_12_doortop) {
581
                id = 6; // Lattice + door A
582
                ybottom += 3;
583
        } else if (curr_tile == tiles_11_loose) {
584
                id = loose_fram_left[get_loose_frame(curr_modifier)];
585
        } else if (curr_tile == tiles_15_opener && tile_left == tiles_0_empty && tbl_level_type[current_level] == 0) {
586
                id = 148; // left half of open button with no floor to the left
587
        } else {
588
                id = tile_table[curr_tile].base_id;
589
        }
590
        ptr_add_table(id_chtab_6_environment, id, draw_xh, 0, tile_table[curr_tile].base_y + ybottom, blitters_10h_transp, 0);
591
}
592
 
593
const byte spikes_fram_left[] = {0, 128, 129, 130, 131, 132, 131, 129, 128, 0};
594
const byte potion_fram_bubb[] = {0, 16, 17, 18, 19, 20, 21, 22};
595
const byte chomper_fram1[] = {3, 2, 0, 1, 4, 3, 3, 0};
596
const byte chomper_fram_bot[] = {101, 102, 103, 104, 105, 0};
597
const byte chomper_fram_top[] = {0, 0, 111, 112, 113, 0};
598
const byte chomper_fram_y[] = {0, 0, 0x25, 0x2F, 0x32};
599
 
600
// seg008:0B2B
601
void __pascal far draw_tile_anim() {
602
        word color;
603
        word pot_size;
604
        word var_4;
605
        pot_size = 0;
606
        color = 12; // red
607
        switch (curr_tile) {
608
                case tiles_2_spike:
609
                        ptr_add_table(id_chtab_6_environment, spikes_fram_left[get_spike_frame(curr_modifier)], draw_xh, 0, draw_main_y - 2, blitters_10h_transp, 0);
610
                        break;
611
                case tiles_10_potion:
612
                        switch((curr_modifier & 0xF8) >> 3) {
613
                                case 0:
614
                                        return; //empty
615
                                case 5: // hurt
616
                                case 6: // open
617
                                        color = 9; // blue
618
                                        break;
619
                                case 3: // slow fall
620
                                case 4: // upside down
621
                                        color = 10; // green
622
                                        // fallthrough!
623
                                case 2: // life
624
                                        pot_size = 1;
625
                                        break;
626
                        }
627
                        add_backtable(id_chtab_1_flameswordpotion, 23 /*bubble mask*/, draw_xh + 3, 1, draw_main_y - (pot_size << 2) - 14, blitters_40h_mono, 0);
628
                        add_foretable(id_chtab_1_flameswordpotion, potion_fram_bubb[curr_modifier & 0x7], draw_xh + 3, 1, draw_main_y - (pot_size << 2) - 14, color + blitters_40h_mono, 0);
629
                        break;
630
                case tiles_22_sword:
631
                        add_midtable(id_chtab_1_flameswordpotion, (curr_modifier == 1) + 10, draw_xh, 0, draw_main_y - 3, blitters_10h_transp, curr_modifier == 1);
632
                        break;
633
                case tiles_18_chomper:
634
                        var_4 = chomper_fram1[MIN(curr_modifier & 0x7F, 6)];
635
                        add_backtable(id_chtab_6_environment, chomper_fram_bot[var_4], draw_xh, 0, draw_main_y, blitters_10h_transp, 0);
636
                        if (curr_modifier & 0x80) { // blood
637
                                add_backtable(id_chtab_6_environment, var_4 + 114, draw_xh + 1, 4, draw_main_y - 6, blitters_4Ch_mono_12, 0);
638
                        }
639
                        add_backtable(id_chtab_6_environment, chomper_fram_top[var_4], draw_xh, 0, draw_main_y - chomper_fram_y[var_4], blitters_10h_transp, 0);
640
                        break;
641
        }
642
}
643
 
644
const byte spikes_fram_fore[] = {0, 139, 140, 141, 142, 143, 142, 140, 139, 0};
645
const byte chomper_fram_for[] = {106, 107, 108, 109, 110, 0};
646
const byte wall_fram_main[] = {8, 10, 6, 4};
647
 
648
// seg008:0D15
649
void __pascal far draw_tile_fore() {
650
        word ybottom;
651
        byte xh;
652
        word potion_type;
653
        word id;
654
        word var_2;
655
        if (tile_left == tiles_4_gate && Kid.curr_row == drawn_row && Kid.curr_col == drawn_col - 1 && Kid.room != room_R) {
656
                draw_gate_fore();
657
        }
658
        switch (curr_tile) {
659
                case tiles_2_spike:
660
                        add_foretable(id_chtab_6_environment, spikes_fram_fore[get_spike_frame(curr_modifier)], draw_xh, 0, draw_main_y - 2, blitters_10h_transp, 0);
661
                        break;
662
                case tiles_18_chomper:
663
                        var_2 = chomper_fram1[MIN(curr_modifier & 0x7F, 6)];
664
                        add_foretable(id_chtab_6_environment, chomper_fram_for[var_2], draw_xh, 0, draw_main_y, blitters_10h_transp, 0);
665
                        if (curr_modifier & 0x80) {
666
                                add_foretable(id_chtab_6_environment, var_2 + 119, draw_xh + 1, 4, draw_main_y - 6, blitters_4Ch_mono_12, 0);
667
                        }
668
                        break;
669
                case tiles_20_wall:
670
                        if (tbl_level_type[current_level] == 0 || enable_wda_in_palace || graphics_mode != gmMcgaVga) {
671
                                add_foretable(id_chtab_7_environmentwall, wall_fram_main[curr_modifier & 0x7F], draw_xh, 0, draw_main_y, blitters_0_no_transp, 0);
672
                        }
673
                        if (graphics_mode != gmCga && graphics_mode != gmHgaHerc) {
674
                                wall_pattern(1, 1);
675
                        }
676
                        break;
677
                default:
678
                        id = tile_table[curr_tile].fore_id;
679
                        if (id == 0) return;
680
                        if (curr_tile == tiles_10_potion) {
681
                                // large pots are drawn for potion types 2, 3, 4
682
                                potion_type = (curr_modifier & 0xF8) >> 3;
683
                                if (potion_type < 5 && potion_type >= 2) id = 13; // small pot = 12, large pot = 13
684
                        }
685
                        xh = tile_table[curr_tile].fore_x + draw_xh;
686
                        ybottom = tile_table[curr_tile].fore_y + draw_main_y;
687
                        if (curr_tile == tiles_10_potion) {
688
                                // potions look different in the dungeon and the palace
689
                                if (tbl_level_type[current_level] != 0) id += 2;
690
                                add_foretable(id_chtab_1_flameswordpotion, id, xh, 6, ybottom, blitters_10h_transp, 0);
691
                        } else {
692
                                if ((curr_tile == tiles_3_pillar && tbl_level_type[current_level] == 0) || (curr_tile >= tiles_27_lattice_small && curr_tile < tiles_30_torch_with_debris)) {
693
                                        add_foretable(id_chtab_6_environment, id, xh, 0, ybottom, blitters_0_no_transp, 0);
694
                                } else {
695
                                        add_foretable(id_chtab_6_environment, id, xh, 0, ybottom, blitters_10h_transp, 0);
696
                                }
697
                        }
698
                        break;
699
        }
700
}
701
 
702
// seg008:0FF6
703
int __pascal far get_loose_frame(byte modifier) {
704
        if (modifier & 0x80) {
705
                modifier &= 0x7F;
706
                if (modifier > 10) {
707
                        return 1;
708
                }
709
        }
710
        return modifier;
711
}
712
 
713
// Get an image, with index and NULL checks.
714
image_type* get_image(short chtab_id, int id) {
715
        if (chtab_id < 0 || chtab_id > COUNT(chtab_addrs)) {
716
                printf("Tried to use chtab %d not in 0..%d\n", chtab_id, (int)COUNT(chtab_addrs));
717
                return NULL;
718
        }
719
        chtab_type* chtab = chtab_addrs[chtab_id];
720
        if (chtab == NULL) {
721
                printf("Tried to use null chtab %d\n", chtab_id);
722
                return NULL;
723
        }
724
        if (id < 0 || id >= chtab->n_images) {
725
                if (id != 255) printf("Tried to use image %d of chtab %d, not in 0..%d\n", id, chtab_id, chtab->n_images-1);
726
                return NULL;
727
        }
728
        return chtab->images[id];
729
}
730
 
731
// seg008:10A8
732
int __pascal far add_backtable(short chtab_id, int id, sbyte xh, sbyte xl, int ybottom, byte blit, byte peel) {
733
        word index;
734
        if (id == 0) {
735
                return 0;
736
        }
737
        index = backtable_count;
738
        if (index >= 200) {
739
                show_dialog("BackTable Overflow");
740
                return 0; // added
741
        }
742
        back_table_type* backtable_item = &backtable[index];
743
        backtable_item->xh = xh;
744
        backtable_item->xl = xl;
745
        backtable_item->chtab_id = chtab_id;
746
        backtable_item->id = id - 1;
747
        image_type* image = get_image(chtab_id, id - 1);
748
        if (image == NULL) {
749
                return 0;
750
        }
751
        backtable_item->y = ybottom - image->h/*height*/ + 1;
752
        backtable_item->blit = blit;
753
        if (draw_mode) {
754
                draw_back_fore(0, index);
755
        }
756
        ++backtable_count;
757
        return 1;
758
}
759
 
760
// seg008:1017
761
int __pascal far add_foretable(short chtab_id, int id, sbyte xh, sbyte xl, int ybottom, byte blit, byte peel) {
762
        word index;
763
        if (id == 0) return 0;
764
        index = foretable_count;
765
        if (index >= 200) {
766
                show_dialog("ForeTable Overflow");
767
                return 0; // added
768
        }
769
        back_table_type* foretable_item = &foretable[index];
770
        foretable_item->xh = xh;
771
        foretable_item->xl = xl;
772
        foretable_item->chtab_id = chtab_id;
773
        foretable_item->id = id - 1;
774
        image_type* image = get_image(chtab_id, id - 1);
775
        if (image == NULL) {
776
                return 0;
777
        }
778
        foretable_item->y = ybottom - image->h/*height*/ + 1;
779
        foretable_item->blit = blit;
780
        if (draw_mode) {
781
                draw_back_fore(1, index);
782
        }
783
        ++foretable_count;
784
        return 1;
785
}
786
 
787
// seg008:113A
788
int __pascal far add_midtable(short chtab_id, int id, sbyte xh, sbyte xl, int ybottom, byte blit, byte peel) {
789
        word index;
790
        if (id == 0) {
791
                return 0;
792
        }
793
        index = midtable_count;
794
        if (index >= 50) {
795
                show_dialog("MidTable Overflow");
796
                return 0; // added
797
        }
798
        midtable_type* midtable_item = &midtable[index];
799
        midtable_item->xh = xh;
800
        midtable_item->xl = xl;
801
        midtable_item->chtab_id = chtab_id;
802
        midtable_item->id = id - 1;
803
        image_type* image = get_image(chtab_id, id - 1);
804
        if (image == NULL) {
805
                return 0;
806
        }
807
        midtable_item->y = ybottom - image->h/*height*/ + 1;
808
        if (obj_direction == dir_0_right && chtab_flip_clip[chtab_id] != 0) {
809
                blit += 0x80;
810
        }
811
        midtable_item->blit = blit;
812
        midtable_item->peel = peel;
813
        midtable_item->clip.left = obj_clip_left;
814
        midtable_item->clip.right = obj_clip_right;
815
        midtable_item->clip.top = obj_clip_top;
816
        midtable_item->clip.bottom = obj_clip_bottom;
817
        if (draw_mode) {
818
                draw_mid(index);
819
        }
820
        ++midtable_count;
821
        return 1;
822
}
823
 
824
// seg008:1208
825
void __pascal far add_peel(int left,int right,int top,int height) {
826
        rect_type rect;
827
        if (peels_count >= 50) {
828
                show_dialog("Peels OverFlow");
829
                return /*0*/; // added
830
        }
831
        rect.left = left;
832
        rect.right = right;
833
        rect.top = top;
834
        rect.bottom = top + height;
835
        peels_table[peels_count++] = read_peel_from_screen(&rect);
836
}
837
 
838
// seg008:1254
839
void __pascal far add_wipetable(sbyte layer,short left,short bottom,sbyte height,short width,sbyte color) {
840
        word index;
841
        index = wipetable_count;
842
        if (index >= 300) {
843
                show_dialog("WipeTable Overflow");
844
                return /*0*/; // added
845
        }
846
        wipetable_type* wipetable_item = &wipetable[index];
847
        wipetable_item->left = left;
848
        wipetable_item->bottom = bottom + 1;
849
        wipetable_item->height = height;
850
        wipetable_item->width = width;
851
        wipetable_item->color = color;
852
        wipetable_item->layer = layer;
853
        if (draw_mode) {
854
                draw_wipe(index);
855
        }
856
        ++wipetable_count;
857
}
858
 
859
// seg008:12BB
860
void __pascal far draw_table(int which_table) {
861
        short index;
862
        short count;
863
        count = table_counts[which_table];
864
        for (index = 0; index < count; ++index) {
865
                if (which_table == 3) {
866
                        draw_mid(index);
867
                } else {
868
                        draw_back_fore(which_table, index);
869
                }
870
        }
871
}
872
 
873
// seg008:12FE
874
void __pascal far draw_wipes(int which) {
875
        word index;
876
        word count;
877
        count = wipetable_count;
878
        for (index = 0; index < count; ++index) {
879
                if (which == wipetable[index].layer) {
880
                        draw_wipe(index);
881
                }
882
        }
883
}
884
 
885
// seg008:133B
886
void __pascal far draw_back_fore(int which_table,int index) {
887
        image_type* image;
888
        image_type* mask;
889
        back_table_type* table_entry;
890
        if (which_table == 0) {
891
                table_entry = &backtable[index];
892
        } else /* if (which_table == 1) this is always true */ {
893
                table_entry = &foretable[index];
894
        }
895
        image = mask = get_image(table_entry->chtab_id, table_entry->id);
896
        /*
897
        if ((graphics_mode == gmCga || graphics_mode == gmHgaHerc) &&
898
                chtab_shift[table_entry->chtab_id] == 0) {
899
                chtab_type* chtab = chtab_addrs[table_entry->chtab_id];
900
                mask = chtab->images[chtab->n_images / 2 + table_entry->id];
901
        }
902
        */
903
        draw_image(image, mask, table_entry->xh * 8 + table_entry->xl, table_entry->y, table_entry->blit);
904
}
905
 
906
 
907
SDL_Surface* hflip(SDL_Surface* input) {
908
        int width = input->w;
909
        int height = input->h;
910
        int source_x, target_x;
911
 
912
        // The simplest way to create a surface with same format as input:
913
        SDL_Surface* output = SDL_ConvertSurface(input, input->format, 0);
914
        SDL_SetSurfacePalette(output, input->format->palette);
915
        // The copied image will be overwritten anyway.
916
        if (output == NULL) {
917
                sdlperror("SDL_ConvertSurface");
918
                quit(1);
919
        }
920
 
921
        SDL_SetSurfaceBlendMode(input, SDL_BLENDMODE_NONE);
922
        // Temporarily turn off alpha and colorkey on input. So we overwrite the output image.
923
        SDL_SetColorKey(input, SDL_FALSE, 0);
924
        SDL_SetColorKey(output, SDL_FALSE, 0);
925
        SDL_SetSurfaceAlphaMod(input, 255);
926
 
927
        for (source_x = 0, target_x = width-1; source_x < width; ++source_x, --target_x) {
928
                SDL_Rect srcrect = {source_x, 0, 1, height};
929
                SDL_Rect dstrect = {target_x, 0, 1, height};
930
                if (SDL_BlitSurface(input/*32*/, &srcrect, output, &dstrect) != 0) {
931
                        sdlperror("SDL_BlitSurface");
932
                        quit(1);
933
                }
934
        }
935
 
936
        return output;
937
}
938
 
939
 
940
// seg008:140C
941
void __pascal far draw_mid(int index) {
942
        word need_free_mask;
943
        word image_id;
944
        image_type*far mask;
945
        word chtab_id;
946
        word blit_flip;
947
        short ypos;
948
        short xpos;
949
        midtable_type* midtable_entry;
950
        word blit;
951
        word need_free_image;
952
        image_type*far image;
953
//      word image_flipped;
954
 
955
        blit_flip = 0;
956
        need_free_image = 0;
957
        need_free_mask = 0;
958
        midtable_entry = &midtable[index];
959
        image_id = midtable_entry->id;
960
        chtab_id = midtable_entry->chtab_id;
961
        image = mask = get_image(chtab_id, image_id);
962
        /*
963
        if ((graphics_mode == gmCga || graphics_mode == gmHgaHerc) && chtab_shift[chtab_id]) {
964
                mask = chtab_addrs[chtab_id]->images[image_id + chtab_addrs[chtab_id]->n_images / 2];
965
        }
966
        */
967
        xpos = midtable_entry->xh * 8 + midtable_entry->xl;
968
        ypos = midtable_entry->y;
969
        blit = midtable_entry->blit;
970
        if (blit & 0x80) {
971
                blit_flip = 0x8000;
972
                blit &= 0x7F;
973
        }
974
 
975
        if (chtab_flip_clip[chtab_id]) {
976
                set_clip_rect(&midtable_entry->clip);
977
                if (chtab_id != id_chtab_0_sword) {
978
                        xpos = calc_screen_x_coord(xpos);
979
                }
980
        }
981
        if (blit_flip) {
982
                xpos -= image->w/*width*/;
983
                // for this version:
984
                need_free_image = 1;
985
                image = hflip(image);
986
        }
987
 
988
        if (midtable_entry->peel) {
989
                add_peel(round_xpos_to_byte(xpos, 0), round_xpos_to_byte(image->w/*width*/ + xpos, 1), ypos, image->h/*height*/);
990
        }
991
        //printf("Midtable: drawing (chtab %d, image %d) at (x=%d, y=%d)\n",chtab_id,image_id,xpos,ypos); // debug
992
        draw_image(image, mask, xpos, ypos, blit);
993
 
994
        if (chtab_flip_clip[chtab_id]) {
995
                reset_clip_rect();
996
        }
997
        if (need_free_image) {
998
                //free_far(image);
999
                SDL_FreeSurface(image);
1000
        }
1001
        if (need_free_mask) {
1002
                free_far(mask);
1003
        }
1004
}
1005
 
1006
// seg008:167B
1007
void __pascal far draw_image(image_type far *image,image_type far *mask,int xpos,int ypos,int blit) {
1008
        rect_type rect;
1009
        switch (blit) {
1010
                case blitters_10h_transp:
1011
                        draw_image_transp(image, mask, xpos, ypos);
1012
                break;
1013
                case blitters_9_black:
1014
                        method_6_blit_img_to_scr(mask, xpos, ypos, blitters_9_black);
1015
                break;
1016
                case blitters_0_no_transp:
1017
                case blitters_2_or:
1018
                case blitters_3_xor:
1019
                        method_6_blit_img_to_scr(image, xpos, ypos, blit);
1020
                break;
1021
                default:
1022
                        method_3_blit_mono(image, xpos, ypos, 0, blit & 0xBF);
1023
                break;
1024
        }
1025
        if (need_drects) {
1026
                rect.left = rect.right = xpos;
1027
                rect.right += image->w/*width*/;
1028
                rect.top = rect.bottom = ypos;
1029
                rect.bottom += image->h/*height*/;
1030
                add_drect(&rect);
1031
        }
1032
}
1033
 
1034
// seg008:1730
1035
void __pascal far draw_wipe(int index) {
1036
        rect_type rect;
1037
        wipetable_type* ptr;
1038
        ptr = &wipetable[index];
1039
        rect.left = rect.right = ptr->left;
1040
        rect.right += ptr->width;
1041
        rect.bottom = rect.top = ptr->bottom;
1042
        rect.top -= ptr->height;
1043
        draw_rect(&rect, ptr->color);
1044
        if (need_drects) {
1045
                add_drect(&rect);
1046
        }
1047
}
1048
 
1049
// data:4E8C
1050
word gate_top_y;
1051
// data:4CB6
1052
word gate_openness;
1053
// data:436C
1054
word gate_bottom_y;
1055
 
1056
// seg008:178E
1057
void __pascal far calc_gate_pos() {
1058
        gate_top_y = draw_bottom_y - 62;
1059
        gate_openness = (MIN(modifier_left, 188) >> 2) + 1;
1060
        gate_bottom_y = draw_main_y - gate_openness;
1061
}
1062
 
1063
// data:2785
1064
const byte door_fram_slice[] = {67, 59, 58, 57, 56, 55, 54, 53, 52};
1065
// seg008:17B7
1066
void __pascal far draw_gate_back() {
1067
        short ybottom;
1068
        word var_2;
1069
        calc_gate_pos();
1070
        if (gate_bottom_y + 12 < draw_main_y) {
1071
                add_backtable(id_chtab_6_environment, 50 /*gate bottom with B*/, draw_xh, 0, gate_bottom_y, blitters_0_no_transp, 0);
1072
        } else {
1073
                // The following line (erroneously) erases the top-right of the tile below-left (because it is drawn non-transparently).
1074
                // -- But it draws something that was already drawn! (in draw_tile_right()).
1075
                add_backtable(id_chtab_6_environment, tile_table[tiles_4_gate].right_id, draw_xh, 0,
1076
                              tile_table[tiles_4_gate].right_y + draw_main_y, blitters_0_no_transp, 0);
1077
                // And this line tries to fix it. But it fails if it was a gate or a pillar.
1078
                if (can_see_bottomleft()) draw_tile_topright();
1079
#ifdef FIX_GATE_DRAWING_BUG
1080
                if (fix_gate_drawing_bug) {
1081
                        draw_tile_anim_topright(); // redraw the erased top-right section of the gate below-left
1082
                }
1083
#endif
1084
                // The following 3 lines draw things that are drawn after this anyway.
1085
                draw_tile_bottom(0);
1086
                draw_loose(0);
1087
                draw_tile_base();
1088
                add_backtable(id_chtab_6_environment, 51 /*gate bottom*/, draw_xh, 0, gate_bottom_y - 2, blitters_10h_transp, 0);
1089
        }
1090
        ybottom = gate_bottom_y - 12;
1091
        if (ybottom < 192) {
1092
                for (; ybottom >= 0 && ybottom > 7 && ybottom - 7 > gate_top_y; ybottom -= 8) {
1093
                        add_backtable(id_chtab_6_environment, 52 /*gate slice 8px*/, draw_xh, 0, ybottom, blitters_0_no_transp, 0);
1094
                }
1095
        }
1096
        var_2 = ybottom - gate_top_y + 1;
1097
        if (var_2 > 0 && var_2 < 9) {
1098
                add_backtable(id_chtab_6_environment, door_fram_slice[var_2], draw_xh, 0, ybottom, blitters_0_no_transp, 0);
1099
        }
1100
}
1101
 
1102
// seg008:18BE
1103
void __pascal far draw_gate_fore() {
1104
        short ybottom;
1105
        calc_gate_pos();
1106
        add_foretable(id_chtab_6_environment, 51 /*gate bottom*/, draw_xh, 0, gate_bottom_y - 2, blitters_10h_transp, 0);
1107
        ybottom = gate_bottom_y - 12;
1108
        if (ybottom < 192) {
1109
                for (; ybottom >= 0 && ybottom > 7 && ybottom - 7 > gate_top_y; ybottom -= 8) {
1110
                        add_foretable(id_chtab_6_environment, 52 /*gate slice 8px*/, draw_xh, 0, ybottom, blitters_10h_transp, 0);
1111
                }
1112
        }
1113
}
1114
 
1115
// seg008:1937
1116
void __pascal far alter_mods_allrm() {
1117
        word tilepos;
1118
        word room;
1119
        for (room = 1; room <= level.used_rooms; room++) {
1120
                get_room_address(room);
1121
                room_L = level.roomlinks[room-1].left;
1122
                room_R = level.roomlinks[room-1].right;
1123
                for(tilepos = 0; tilepos < 30; tilepos++) {
1124
                        load_alter_mod(tilepos);
1125
                }
1126
        }
1127
}
1128
 
1129
// seg008:198E
1130
void __pascal far load_alter_mod(int tilepos) {
1131
        word wall_to_right;
1132
        word tiletype;
1133
        word wall_to_left;
1134
        byte* curr_tile_modif;
1135
        curr_tile_modif = tilepos + curr_room_modif;
1136
        tiletype = curr_room_tiles[tilepos] & 0x1F;
1137
        switch (tiletype) {
1138
                case tiles_4_gate:
1139
                        if (*curr_tile_modif == 1) {
1140
                                *curr_tile_modif = 188;
1141
                        } else {
1142
                                *curr_tile_modif = 0;
1143
                        }
1144
                        break;
1145
                case tiles_11_loose:
1146
                        *curr_tile_modif = 0;
1147
                        break;
1148
                case tiles_10_potion:
1149
                        *curr_tile_modif <<= 3;
1150
#ifdef USE_COPYPROT
1151
                        if (current_level == 15) {
1152
                                // Copy protection
1153
                                if (copyprot_room[copyprot_plac] == loaded_room &&
1154
                                        copyprot_tile[copyprot_plac] == tilepos
1155
                                ) {
1156
                                        *curr_tile_modif = 6 << 3; // place open potion
1157
                                }
1158
                        }
1159
#endif
1160
                        break;
1161
 
1162
 
1163
                case tiles_20_wall:
1164
                {
1165
                        byte stored_modif = *curr_tile_modif;
1166
                        //*curr_tile_modif <<= 7; // original: "no blue" mod becomes most significant bit
1167
                        if (stored_modif == 1) *curr_tile_modif = 0x80;
1168
                        else *curr_tile_modif = (stored_modif << 4);
1169
                        // retain three bits more information:
1170
                        // most significant bit:       1 ==> "no blue"
1171
                        // next 3 bits:                for displaying various fake tiles (invisible walls)
1172
                        // ..
1173
                        // least significant 2 bits:   wall to left/right?
1174
                }
1175
                        // fallthrough: not done yet, just moving to another scope
1176
                        goto label_wall_continued;
1177
 
1178
#ifdef USE_FAKE_TILES
1179
                // Need to deal with the possibility that certain tiles can impersonate walls
1180
                case tiles_0_empty:
1181
                case tiles_1_floor:
1182
                        if ((*curr_tile_modif & 7) != 5) break;
1183
                        // if tile is a fake wall, fall through
1184
#endif
1185
 
1186
                        label_wall_continued:
1187
                {
1188
                        // Here, ahead of time, we define the condition for a neighbouring tile to be seen as a wall connection
1189
                        #ifndef USE_FAKE_TILES
1190
                        #define read_adj_tile_modif_in_curr_room()      // nop; access to modifier of adjacent tiles is not needed
1191
                        #define read_adj_tile_modif_in_external_room()  // nop
1192
                        #define WALL_CONNECTION_CONDITION (adj_tile == tiles_20_wall)
1193
 
1194
                        #else // #ifdef USE_FAKE_TILES
1195
                        // When determining wall connections for fake walls, we need access to the tile modifier of adjacent tiles
1196
                        #define read_adj_tile_modif_in_curr_room() \
1197
                        int adj_tile_modif = curr_room_modif[adj_tile_index];
1198
                        #define read_adj_tile_modif_in_external_room() \
1199
                        int adj_tile_modif = level.bg[adj_tile_index];
1200
                        // Now redefine the condition for what tiletype / modifier combination counts as a valid "wall"
1201
                        #define WALL_CONNECTION_CONDITION (                                                                       \
1202
                                (adj_tile == tiles_20_wall && adj_tile_modif != 4 && (adj_tile_modif >> 4) != 4 &&                    \
1203
                                             adj_tile_modif != 6 && (adj_tile_modif >> 4) != 6) ||                                    \
1204
                                (adj_tile == tiles_0_empty && (adj_tile_modif == 5 || adj_tile_modif == 13 ||                         \
1205
                                             (adj_tile_modif >= 50 && adj_tile_modif <= 53))) ||                                      \
1206
                                (adj_tile == tiles_1_floor && (adj_tile_modif == 5 || adj_tile_modif == 13 ||                         \
1207
                                             (adj_tile_modif >= 50 && adj_tile_modif <= 53))))
1208
                        #endif
1209
 
1210
                        if (graphics_mode != gmCga && graphics_mode != gmHgaHerc) {
1211
                                wall_to_right = 1;
1212
                                wall_to_left = 1;
1213
                                int adj_tile_index, adj_tile;
1214
                                if (tilepos % 10 == 0) {
1215
                                        if (room_L) {
1216
                                                adj_tile_index = 30*(room_L-1)+tilepos+9;
1217
                                                adj_tile = (level.fg[adj_tile_index] & 0x1F);
1218
                                                read_adj_tile_modif_in_external_room(); // only executed when fake tiles are enabled
1219
                                                wall_to_left = WALL_CONNECTION_CONDITION;
1220
                                        }
1221
                                } else {
1222
                                        adj_tile_index = tilepos-1;
1223
                                        adj_tile = (curr_room_tiles[adj_tile_index] & 0x1F);
1224
                                        read_adj_tile_modif_in_curr_room();
1225
                                        wall_to_left = WALL_CONNECTION_CONDITION;
1226
                                }
1227
                                if (tilepos % 10 == 9) {
1228
                                        if (room_R) {
1229
                                                adj_tile_index = 30*(room_R-1)+tilepos-9;
1230
                                                adj_tile = (level.fg[adj_tile_index] & 0x1F);
1231
                                                read_adj_tile_modif_in_external_room();
1232
                                                wall_to_right = WALL_CONNECTION_CONDITION;
1233
                                        }
1234
                                } else {
1235
                                        adj_tile_index = tilepos+1;
1236
                                        adj_tile = (curr_room_tiles[adj_tile_index] & 0x1F);
1237
                                        read_adj_tile_modif_in_curr_room();
1238
                                        wall_to_right = WALL_CONNECTION_CONDITION;
1239
                                }
1240
 
1241
                                #ifdef USE_FAKE_TILES
1242
                                if (tiletype == tiles_1_floor || tiletype == tiles_0_empty) {
1243
                                        if (wall_to_left && wall_to_right) {
1244
                                                *curr_tile_modif = 53;
1245
                                        } else if (wall_to_left) {
1246
                                                *curr_tile_modif = 52;
1247
                                        } else if (wall_to_right) {
1248
                                                *curr_tile_modif = 51;
1249
                                        }
1250
                                        break;
1251
                                }
1252
                                #endif
1253
 
1254
                                if (wall_to_left && wall_to_right) {
1255
                                        *curr_tile_modif |= 3;
1256
                                } else if (wall_to_left) {
1257
                                        *curr_tile_modif |= 2;
1258
                                } else if (wall_to_right) {
1259
                                        *curr_tile_modif |= 1;
1260
                                }
1261
                        } else {
1262
                                *curr_tile_modif = 3;
1263
                        }
1264
                }
1265
                        break;
1266
        }
1267
}
1268
 
1269
// seg008:1AF8
1270
void __pascal far draw_moving() {
1271
        draw_mobs();
1272
        draw_people();
1273
        redraw_needed_tiles();
1274
}
1275
 
1276
// seg008:1B06
1277
void __pascal far redraw_needed_tiles() {
1278
        word saved_drawn_room;
1279
        load_leftroom();
1280
        draw_objtable_items_at_tile(30);
1281
        for (drawn_row = 3; drawn_row--; ) {
1282
                load_rowbelow();
1283
                draw_bottom_y = 63 * drawn_row + 65;
1284
                draw_main_y = draw_bottom_y - 3;
1285
                for (drawn_col = 0; drawn_col < 10; ++drawn_col) {
1286
                        load_curr_and_left_tile();
1287
                        redraw_needed(tbl_line[drawn_row] + drawn_col);
1288
                }
1289
        }
1290
        saved_drawn_room = drawn_room;
1291
        drawn_room = room_A;
1292
        load_room_links();
1293
        load_leftroom();
1294
        drawn_row = 2;
1295
        load_rowbelow();
1296
        for (drawn_col = 0; drawn_col < 10; ++drawn_col) {
1297
                load_curr_and_left_tile();
1298
                draw_main_y = -1;
1299
                draw_bottom_y = 2;
1300
                redraw_needed_above(drawn_col);
1301
        }
1302
        drawn_room = saved_drawn_room;
1303
        load_room_links();
1304
        draw_objtable_items_at_tile(-1);
1305
}
1306
 
1307
// seg008:1BCB
1308
void __pascal far draw_tile_wipe(byte height) {
1309
        add_wipetable(0, draw_xh*8, draw_bottom_y, height, 4*8, 0);
1310
}
1311
 
1312
// seg008:1BEB
1313
void __pascal far draw_tables() {
1314
        drects_count = 0;
1315
        current_target_surface = offscreen_surface;
1316
        if (is_blind_mode) {
1317
                draw_rect(&rect_top, 0);
1318
        }
1319
        restore_peels();
1320
        draw_wipes(0);
1321
        draw_table(0); // backtable
1322
        //printf("midtable_count = %d\n", midtable_count); // debug
1323
        draw_table(3); // midtable
1324
        draw_wipes(1);
1325
        draw_table(1); // foretable
1326
        current_target_surface = onscreen_surface_;
1327
        show_copyprot(1);
1328
}
1329
 
1330
// seg008:1C4E
1331
void __pascal far restore_peels() {
1332
        peel_type* peel;
1333
        while (peels_count--) {
1334
                peel = peels_table[peels_count];
1335
                if (need_drects) {
1336
                        add_drect(&peel->rect); // ?
1337
                }
1338
                restore_peel(peel);
1339
        }
1340
        peels_count = 0;
1341
}
1342
 
1343
// seg008:1C8F
1344
void __pascal far add_drect(rect_type *source) {
1345
        rect_type* far current_drect;
1346
        short index;
1347
        rect_type target_rect;
1348
        for (index = 0; index < drects_count; ++index) {
1349
                if (intersect_rect(&target_rect, shrink2_rect(&target_rect, source, -1, -1), &drects[index])) {
1350
                        current_drect = &drects[index];
1351
                        union_rect(current_drect, current_drect, source);
1352
                        return;
1353
                }
1354
        }
1355
        if (drects_count >= 30){
1356
                show_dialog("DRects Overflow");
1357
                return /*0*/; // added
1358
        }
1359
        drects[drects_count++] = *source;
1360
}
1361
 
1362
// seg008:1D29
1363
void __pascal far draw_leveldoor() {
1364
        word var_6;
1365
        word ybottom;
1366
        ybottom = draw_main_y - 13;
1367
        leveldoor_right = (draw_xh<<3)+48;
1368
        if (tbl_level_type[current_level]) leveldoor_right += 8;
1369
        add_backtable(id_chtab_6_environment, 99 /*leveldoor stairs bottom*/, draw_xh + 1, 0, ybottom, blitters_0_no_transp, 0);
1370
        if (modifier_left) {
1371
                if (level.start_room != drawn_room) {
1372
                        add_backtable(id_chtab_6_environment, 144 /*level door stairs*/, draw_xh + 1, 0, ybottom - 4, blitters_0_no_transp, 0);
1373
                }
1374
                else {
1375
                        short leveldoor_width = (tbl_level_type[current_level] == 0) ? 39 : 48;
1376
                        sbyte x_low = (tbl_level_type[current_level] == 0) ? 2 : 0; // dungeon level doors are shifted 2px to the right
1377
                        add_wipetable(0, 8*(draw_xh + 1) + x_low, ybottom - 4, 45, leveldoor_width, 0);
1378
                }
1379
        }
1380
        leveldoor_ybottom = ybottom - (modifier_left & 3) - 48;
1381
        for (var_6 = ybottom - modifier_left;
1382
                add_backtable(id_chtab_6_environment, 33 /*level door bottom*/, draw_xh + 1, 0, leveldoor_ybottom, blitters_0_no_transp, 0),
1383
                        var_6 > leveldoor_ybottom;
1384
                leveldoor_ybottom += 4) {
1385
                ;
1386
        } // runs at least once?
1387
        add_backtable(id_chtab_6_environment, 34 /*level door top*/, draw_xh + 1, 0, draw_main_y - 64, blitters_0_no_transp, 0);
1388
}
1389
 
1390
// seg008:1E0C
1391
void __pascal far get_room_address(int room) {
1392
        loaded_room = (word) room;
1393
        if (room) {
1394
                curr_room_tiles = &level.fg[(room-1)*30];
1395
                curr_room_modif = &level.bg[(room-1)*30];
1396
        }
1397
}
1398
 
1399
// data:286A
1400
const word floor_left_overlay[] = {32, 151, 151, 150, 150, 151, 32, 32};
1401
 
1402
// seg008:1E3A
1403
void __pascal far draw_floor_overlay() {
1404
#ifdef FIX_BIGPILLAR_CLIMB
1405
        if (tile_left != tiles_0_empty) {
1406
                // Bug: When climbing up to a floor with a big pillar top behind, turned right, Kid sees through floor.
1407
                // The bigpillar_top tile should be treated similarly to an empty tile here.
1408
                if (!fix_bigpillar_climb || (tile_left != tiles_9_bigpillar_top)) {
1409
                        return;
1410
                }
1411
        }
1412
#else
1413
        if (tile_left != tiles_0_empty) return;
1414
#endif
1415
        if (curr_tile == tiles_1_floor ||
1416
                curr_tile == tiles_3_pillar ||
1417
                curr_tile == tiles_5_stuck ||
1418
                curr_tile == tiles_19_torch
1419
        ) {
1420
                // frames 137..144: climb
1421
                // index overflow here?
1422
                if (Kid.frame >= frame_137_climbing_3 && Kid.frame <= frame_144_climbing_10) {
1423
                        add_midtable(id_chtab_6_environment, floor_left_overlay[Kid.frame - 137], draw_xh, 0, (curr_tile == tiles_5_stuck) + draw_main_y, blitters_10h_transp, 0);
1424
                } else {
1425
                        // triggered by 02-random-broken
1426
                        printf("draw_floor_overlay: attempted to draw floor overlay with frame %d not in 137..144\n", Kid.frame);
1427
                        //quit(1);
1428
                }
1429
                ptr_add_table = &add_midtable;
1430
                draw_tile_bottom(0);
1431
                ptr_add_table = &add_backtable;
1432
        } else {
1433
                draw_other_overlay();
1434
        }
1435
}
1436
 
1437
// seg008:1EB5
1438
void __pascal far draw_other_overlay() {
1439
        byte tiletype;
1440
        byte modifier;
1441
        if (tile_left == tiles_0_empty) {
1442
                ptr_add_table = &add_midtable;
1443
                draw_tile2();
1444
        } else if (curr_tile != tiles_0_empty && drawn_col > 0 &&
1445
                get_tile_to_draw(drawn_room, drawn_col - 2, drawn_row, &tiletype, &modifier, tiles_0_empty) == tiles_0_empty
1446
        ) {
1447
                ptr_add_table = &add_midtable;
1448
                draw_tile2();
1449
                ptr_add_table = &add_backtable;
1450
                draw_tile2();
1451
                tile_object_redraw[tbl_line[drawn_row] + drawn_col] = 0xFF;
1452
        }
1453
        ptr_add_table = &add_backtable;
1454
}
1455
 
1456
// seg008:1F48
1457
void __pascal far draw_tile2() {
1458
        draw_tile_right();
1459
        draw_tile_anim_right();
1460
        draw_tile_base();
1461
        draw_tile_anim();
1462
        draw_tile_bottom(0);
1463
        draw_loose(0);
1464
}
1465
 
1466
// seg008:1F67
1467
void __pascal far draw_objtable_items_at_tile(byte tilepos) {
1468
        //printf("draw_objtable_items_at_tile(%d)\n",tilepos); // debug
1469
        short obj_count;
1470
        short obj_index;
1471
        obj_count = objtable_count;
1472
        if (obj_count) {
1473
                for (obj_index = obj_count - 1, n_curr_objs = 0; obj_index >= 0; --obj_index) {
1474
                        if (objtable[obj_index].tilepos == tilepos) {
1475
                                curr_objs[n_curr_objs++] = obj_index;
1476
                        }
1477
                }
1478
                if (n_curr_objs) {
1479
                        sort_curr_objs();
1480
                        for (obj_index = 0; obj_index < n_curr_objs; ++obj_index) {
1481
                                draw_objtable_item(curr_objs[obj_index]);
1482
                        }
1483
                }
1484
        }
1485
}
1486
 
1487
// seg008:1FDE
1488
void __pascal far sort_curr_objs() {
1489
        short swapped;
1490
        short temp;
1491
        short last;
1492
        short index;
1493
        // bubble sort
1494
        last = n_curr_objs - 1;
1495
        do {
1496
                for (swapped = index = 0; index < last; ++index) {
1497
                        if (compare_curr_objs(index, index + 1)) {
1498
                                temp = curr_objs[index];
1499
                                curr_objs[index] = curr_objs[index + 1];
1500
                                curr_objs[index + 1] = temp;
1501
                                swapped = 1;
1502
                        }
1503
                }
1504
                // --last ?
1505
        } while (swapped);
1506
}
1507
 
1508
// seg008:203C
1509
int __pascal far compare_curr_objs(int index1,int index2) {
1510
        short obj_index1;
1511
        short obj_index2;
1512
        obj_index1 = curr_objs[index1];
1513
        if (objtable[obj_index1].obj_type == 1) return 1;
1514
        obj_index2 = curr_objs[index2];
1515
        if (objtable[obj_index2].obj_type == 1) return 0;
1516
        if (objtable[obj_index1].obj_type == 0x80 &&
1517
                objtable[obj_index2].obj_type == 0x80
1518
        ) {
1519
                return (objtable[obj_index1].y < objtable[obj_index2].y);
1520
        } else {
1521
                return (objtable[obj_index1].y > objtable[obj_index2].y);
1522
        }
1523
        return 1;
1524
}
1525
 
1526
// seg008:20CA
1527
void __pascal far draw_objtable_item(int index) {
1528
        switch (load_obj_from_objtable(index)) {
1529
                case 0: // Kid
1530
                case 4: // mirror image
1531
                        //printf("index = %d, obj_id = %d\n", index, obj_id); // debug
1532
                        if (obj_id == 0xFF) return;
1533
                        // the Kid blinks a bit after uniting with shadow
1534
                        if (united_with_shadow && (united_with_shadow % 2) == 0) goto shadow;
1535
                case 2: // Guard
1536
                case 3: // sword
1537
                case 5: // hurt splash
1538
                        add_midtable(obj_chtab, obj_id + 1, obj_xh, obj_xl, obj_y, blitters_10h_transp, 1);
1539
                break;
1540
                case 1: // shadow
1541
                shadow:
1542
                        if (united_with_shadow == 2) {
1543
                                play_sound(sound_41_end_level_music); // united with shadow
1544
                        }
1545
                        add_midtable(obj_chtab, obj_id + 1, obj_xh, obj_xl, obj_y, blitters_2_or, 1);
1546
                        add_midtable(obj_chtab, obj_id + 1, obj_xh, obj_xl + 1, obj_y, blitters_3_xor, 1);
1547
                break;
1548
                case 0x80: // loose floor
1549
                        obj_direction = dir_FF_left;
1550
                        add_midtable(obj_chtab, loose_fram_left[obj_id], obj_xh, obj_xl, obj_y - 3, blitters_10h_transp, 1);
1551
                        add_midtable(obj_chtab, loose_fram_bottom[obj_id], obj_xh, obj_xl, obj_y, 0, 1);
1552
                        add_midtable(obj_chtab, loose_fram_right[obj_id], obj_x + 4, obj_xl, obj_y - 1, blitters_10h_transp, 1);
1553
                break;
1554
        }
1555
}
1556
 
1557
// seg008:2228
1558
int __pascal far load_obj_from_objtable(int index) {
1559
        objtable_type* curr_obj;
1560
        curr_obj = &objtable[index];
1561
        obj_xh = obj_x = curr_obj->xh;
1562
        obj_xl = curr_obj->xl;
1563
        obj_y = curr_obj->y;
1564
        obj_id = curr_obj->id;
1565
        obj_chtab = curr_obj->chtab_id;
1566
        obj_direction = curr_obj->direction;
1567
        obj_clip_top = curr_obj->clip.top;
1568
        obj_clip_bottom = curr_obj->clip.bottom;
1569
        obj_clip_left = curr_obj->clip.left;
1570
        obj_clip_right = curr_obj->clip.right;
1571
        return curr_obj->obj_type;
1572
}
1573
 
1574
// seg008:228A
1575
void __pascal far draw_people() {
1576
        check_mirror();
1577
        draw_kid();
1578
        draw_guard();
1579
        reset_obj_clip();
1580
        draw_hp();
1581
}
1582
 
1583
// seg008:22A2
1584
void __pascal far draw_kid() {
1585
        if (Kid.room != 0 && Kid.room == drawn_room) {
1586
                add_kid_to_objtable();
1587
                if (hitp_delta < 0) {
1588
                        draw_hurt_splash();
1589
                }
1590
                add_sword_to_objtable();
1591
        }
1592
}
1593
 
1594
// seg008:22C9
1595
void __pascal far draw_guard() {
1596
        if (Guard.direction != dir_56_none && Guard.room == drawn_room) {
1597
                add_guard_to_objtable();
1598
                if (guardhp_delta < 0) {
1599
                        draw_hurt_splash();
1600
                }
1601
                add_sword_to_objtable();
1602
        }
1603
}
1604
 
1605
// seg008:22F0
1606
void __pascal far add_kid_to_objtable() {
1607
        //printf("add_kid_to_objtable\n");
1608
        loadkid();
1609
        load_fram_det_col();
1610
        load_frame_to_obj();
1611
        stuck_lower();
1612
        set_char_collision();
1613
        set_objtile_at_char();
1614
        redraw_at_char();
1615
        redraw_at_char2();
1616
        clip_char();
1617
        add_objtable(0); // Kid
1618
}
1619
 
1620
// seg008:2324
1621
void __pascal far add_guard_to_objtable() {
1622
        word obj_type;
1623
        loadshad();
1624
        load_fram_det_col();
1625
        load_frame_to_obj();
1626
        stuck_lower();
1627
        set_char_collision();
1628
        set_objtile_at_char();
1629
        redraw_at_char();
1630
        redraw_at_char2();
1631
        clip_char();
1632
        if (Char.charid == charid_1_shadow) {
1633
                // Special event: shadow is clipped: may appear only right from the mirror
1634
                if (current_level == 4 && Char.room == 4) {
1635
                        obj_clip_left = 137;
1636
                }
1637
                obj_type = 1; // shadow
1638
        } else {
1639
                obj_type = 2; // Guard
1640
        }
1641
        add_objtable(obj_type);
1642
}
1643
 
1644
// seg008:2388
1645
void __pascal far add_objtable(byte obj_type) {
1646
        word index;
1647
        objtable_type* entry_addr;
1648
        //printf("in add_objtable: objtable_count = %d\n",objtable_count); // debug
1649
        index = objtable_count++;
1650
        //printf("in add_objtable: objtable_count = %d\n",objtable_count); // debug
1651
        if (index >= 50) {
1652
                show_dialog("ObjTable Overflow");
1653
                return /*0*/; // added
1654
        }
1655
        entry_addr = &objtable[index];
1656
        entry_addr->obj_type = obj_type;
1657
        x_to_xh_and_xl(obj_x, &entry_addr->xh, &entry_addr->xl);
1658
        entry_addr->y = obj_y;
1659
        entry_addr->clip.top = obj_clip_top;
1660
        entry_addr->clip.bottom = obj_clip_bottom;
1661
        entry_addr->clip.left = obj_clip_left;
1662
        entry_addr->clip.right = obj_clip_right;
1663
        entry_addr->chtab_id = obj_chtab;
1664
        entry_addr->id = obj_id;
1665
        entry_addr->direction = obj_direction;
1666
        mark_obj_tile_redraw(index);
1667
}
1668
 
1669
// seg008:2423
1670
void __pascal far mark_obj_tile_redraw(int index) {
1671
        //printf("mark_obj_tile_redraw: obj_tile = %d\n", obj_tile); // debug
1672
        objtable[index].tilepos = obj_tilepos;
1673
        if (obj_tilepos < 30) {
1674
                tile_object_redraw[obj_tilepos] = 1;
1675
        }
1676
}
1677
 
1678
// seg008:2448
1679
void __pascal far load_frame_to_obj() {
1680
        word chtab_base;
1681
        chtab_base = id_chtab_2_kid;
1682
        reset_obj_clip();
1683
        load_frame();
1684
        obj_direction = Char.direction;
1685
        obj_id = cur_frame.image;
1686
        // top 6 bits of sword are the chtab
1687
        obj_chtab = chtab_base + (cur_frame.sword >> 6);
1688
        obj_x = (char_dx_forward(cur_frame.dx) << 1) - 116;
1689
        obj_y = cur_frame.dy + Char.y;
1690
        if ((sbyte)(cur_frame.flags ^ obj_direction) >= 0) {
1691
                // 0x80: even/odd pixel
1692
                ++obj_x;
1693
        }
1694
}
1695
 
1696
// seg008:24A8
1697
void __pascal far show_time() {
1698
        char sprintf_temp[40];
1699
        word rem_sec;
1700
        if (Kid.alive < 0 &&
1701
                #ifdef FREEZE_TIME_DURING_END_MUSIC
1702
                (!(enable_freeze_time_during_end_music && next_level != current_level)) &&
1703
                #endif
1704
                #ifdef ALLOW_INFINITE_TIME
1705
                // prevent overflow
1706
                (!(rem_min == INT16_MIN && rem_tick == 1)) &&
1707
                #endif
1708
                rem_min != 0 &&
1709
                (current_level < 13 || (current_level == 13 && leveldoor_open == 0)) &&
1710
                current_level < 15
1711
        ) {
1712
                // Time passes
1713
                --rem_tick;
1714
                if (rem_tick == 0) {
1715
                        rem_tick = 719; // 720=12*60 ticks = 1 minute
1716
                        --rem_min;
1717
#ifndef ALLOW_INFINITE_TIME
1718
                        if (rem_min != 0 && (rem_min <= 5 || rem_min % 5 == 0)) {
1719
                                is_show_time = 1;
1720
                        }
1721
#else
1722
                        if (rem_min > 0 && (rem_min <= 5 || rem_min % 5 == 0)) {
1723
                                is_show_time = 1;
1724
                        } else if (rem_min < 0) {
1725
                                is_show_time = ((~rem_min) % 5 == 0 ) ? 1 : 0;
1726
                        }
1727
#endif
1728
                } else {
1729
                        if (rem_min == 1 && rem_tick % 12 == 0) {
1730
                                is_show_time = 1;
1731
                                text_time_remaining = 0;
1732
                        }
1733
                }
1734
        }
1735
        if (is_show_time && text_time_remaining == 0) {
1736
                text_time_remaining = text_time_total = 24;
1737
                if (rem_min > 0) {
1738
                        if (rem_min == 1) {
1739
                                rem_sec = (rem_tick + 1) / 12;
1740
                                if (rem_sec == 1) {
1741
                                        strncpy(sprintf_temp, "1 SECOND LEFT", sizeof(sprintf_temp));
1742
                                        text_time_remaining = text_time_total = 12;
1743
                                } else {
1744
                                        snprintf(sprintf_temp, sizeof(sprintf_temp), "%d SECONDS LEFT", rem_sec);
1745
                                }
1746
                        } else {
1747
                                snprintf(sprintf_temp, sizeof(sprintf_temp), "%d MINUTES LEFT", rem_min);
1748
                        }
1749
                        display_text_bottom(sprintf_temp);
1750
                } else {
1751
 
1752
#ifdef ALLOW_INFINITE_TIME
1753
                        if (rem_min < 0) {
1754
                                if (~rem_min == 0) {
1755
                                        // don't display time elapsed in the first minute
1756
                                        text_time_remaining = 0;
1757
                                        text_time_total = 0;
1758
                                }
1759
                                else if (~rem_min == 1) {
1760
                                        snprintf(sprintf_temp, sizeof(sprintf_temp), "1 MINUTE PASSED");
1761
                                } else {
1762
                                        snprintf(sprintf_temp, sizeof(sprintf_temp), "%d MINUTES PASSED", ~rem_min);
1763
                                }
1764
                                display_text_bottom(sprintf_temp);
1765
                        }
1766
 
1767
                        else if (rem_min == 0) // may also be negative, don't report "expired" in that case!
1768
#endif
1769
 
1770
                        display_text_bottom("TIME HAS EXPIRED!");
1771
                }
1772
                is_show_time = 0;
1773
        }
1774
}
1775
 
1776
// seg008:25A8
1777
void __pascal far show_level() {
1778
        byte disp_level;
1779
        char sprintf_temp[32];
1780
        disp_level = current_level;
1781
        if (disp_level != 0 && disp_level < 14 && seamless == 0) {
1782
                if (disp_level == 13) {
1783
                        disp_level = 12;
1784
                }
1785
                text_time_remaining = text_time_total = 24;
1786
                snprintf(sprintf_temp, sizeof(sprintf_temp), "LEVEL %d", disp_level);
1787
                display_text_bottom(sprintf_temp);
1788
                is_show_time = 1;
1789
        }
1790
        seamless = 0;
1791
}
1792
 
1793
// seg008:2602
1794
short __pascal far calc_screen_x_coord(short logical_x) {
1795
        return logical_x*320/280;
1796
}
1797
 
1798
// seg008:2627
1799
void __pascal far free_peels() {
1800
        while (peels_count > 0) {
1801
                --peels_count;
1802
                free_peel(peels_table[peels_count]);
1803
        }
1804
}
1805
 
1806
 
1807
// seg008:2644
1808
void __pascal far display_text_bottom(const char near *text) {
1809
        draw_rect(&rect_bottom_text, 0);
1810
        show_text(&rect_bottom_text, 0, 1, text);
1811
#ifndef USE_TEXT
1812
        SDL_WM_SetCaption(text, NULL);
1813
#endif
1814
}
1815
 
1816
// seg008:266D
1817
void __pascal far erase_bottom_text(int arg_0) {
1818
        draw_rect(&rect_bottom_text, 0);
1819
        if (arg_0) {
1820
                text_time_total = 0;
1821
                text_time_remaining = 0;
1822
        }
1823
#ifndef USE_TEXT
1824
        SDL_WM_SetCaption("", NULL);
1825
#endif
1826
}
1827
 
1828
// Dungeon wall drawing algorithm by HTamas
1829
 
1830
#define RSET_WALL              7
1831
 
1832
#define RES_WALL_FACE_MAIN     1    //(face stack main.bmp)
1833
#define RES_WALL_FACE_TOP      2    //(face stack top.bmp)
1834
#define RES_WALL_CENTRE_BASE   3    //(centre stack base.bmp)
1835
#define RES_WALL_CENTRE_MAIN   4    //(centre stack main.bmp)
1836
#define RES_WALL_RIGHT_BASE    5    //(right stack base.bmp)
1837
#define RES_WALL_RIGHT_MAIN    6    //(right stack main.bmp)
1838
#define RES_WALL_SINGLE_BASE   7    //(single stack base.bmp)
1839
#define RES_WALL_SINGLE_MAIN   8    //(single stack main.bmp)
1840
#define RES_WALL_LEFT_BASE     9    //(left stack base.bmp)
1841
#define RES_WALL_LEFT_MAIN    10    //(left stack main.bmp)
1842
#define RES_WALL_DIVIDER1     11    //(divider01.bmp, the broad divider)
1843
#define RES_WALL_DIVIDER2     12    //(divider02.bmp, the narrow divider)
1844
#define RES_WALL_RNDBLOCK     13    //(random block.bmp)
1845
#define RES_WALL_MARK_TL      14    //(mark01.bmp, top left mark)
1846
#define RES_WALL_MARK_BL      15    //(mark02.bmp, bottom left mark)
1847
#define RES_WALL_MARK_TR      16    //(mark03.bmp, top right mark)
1848
#define RES_WALL_MARK_BR      17    //(mark04.bmp, bottom right mark)
1849
 
1850
#define BLIT_NO_TRANS          0
1851
#define BLIT_OR                2
1852
#define BLIT_XOR               3
1853
#define BLIT_BLACK             9
1854
#define BLIT_TRANS            16
1855
 
1856
#define GRAPHICS_CGA          1
1857
#define GRAPHICS_HERCULES     2
1858
#define GRAPHICS_EGA          3
1859
#define GRAPHICS_TANDY        4
1860
#define GRAPHICS_VGA          5
1861
 
1862
#define DESIGN_DUNGEON        0
1863
#define DESIGN_PALACE         1
1864
 
1865
#define WALL_MODIFIER_SWS     0
1866
#define WALL_MODIFIER_SWW     1
1867
#define WALL_MODIFIER_WWS     2
1868
#define WALL_MODIFIER_WWW     3
1869
 
1870
 
1871
// seg008:268F
1872
void __pascal far wall_pattern(int which_part,int which_table) {
1873
        // local variables
1874
        add_table_type saved_sim;
1875
        word v2; word v3; byte v4; byte v5;
1876
        byte bg_modifier;
1877
        dword saved_prng_state;
1878
        word is_dungeon;
1879
        // save the value for the sprite insertion method, so that it can be restored
1880
        saved_sim = ptr_add_table;
1881
        // set the sprite insertion method based on the arguments
1882
        if (which_table == 0) {
1883
                ptr_add_table = &add_backtable;
1884
        } else {
1885
                ptr_add_table = &add_foretable;
1886
        }
1887
        // save the state of the pseudorandom number generator
1888
        saved_prng_state = random_seed;
1889
        // set the new seed
1890
        random_seed = drawn_room + tbl_line[drawn_row] + drawn_col;
1891
        prandom(1); // fetch a random number and discard it
1892
        is_dungeon = (tbl_level_type[current_level] < DESIGN_PALACE) || enable_wda_in_palace;
1893
        if ( (!is_dungeon) && (graphics_mode== GRAPHICS_VGA) ) {
1894
                // I haven't traced the palace WDA
1895
                //[...]
1896
                if (which_part) {
1897
                        add_wipetable(which_table, 8*(draw_xh)    , draw_main_y - 40, 20, 4*8, palace_wall_colors[44 * drawn_row +      drawn_col]);
1898
                        add_wipetable(which_table, 8*(draw_xh)    , draw_main_y - 19, 21, 2*8, palace_wall_colors[44 * drawn_row + 11 + drawn_col]);
1899
                        add_wipetable(which_table, 8*(draw_xh + 2), draw_main_y - 19, 21, 2*8, palace_wall_colors[44 * drawn_row + 12 + drawn_col]);
1900
                        add_wipetable(which_table, 8*(draw_xh)    , draw_main_y     , 19, 1*8, palace_wall_colors[44 * drawn_row + 22 + drawn_col]);
1901
                        add_wipetable(which_table, 8*(draw_xh + 1), draw_main_y     , 19, 3*8, palace_wall_colors[44 * drawn_row + 23 + drawn_col]);
1902
                        ptr_add_table(id_chtab_7_environmentwall, prandom(2) +  3, draw_xh + 3, 0, draw_main_y - 53, blitters_46h_mono_6, 0);
1903
                        ptr_add_table(id_chtab_7_environmentwall, prandom(2) +  6, draw_xh    , 0, draw_main_y - 34, blitters_46h_mono_6, 0);
1904
                        ptr_add_table(id_chtab_7_environmentwall, prandom(2) +  9, draw_xh    , 0, draw_main_y - 13, blitters_46h_mono_6, 0);
1905
                        ptr_add_table(id_chtab_7_environmentwall, prandom(2) + 12, draw_xh    , 0, draw_main_y     , blitters_46h_mono_6, 0);
1906
                }
1907
                add_wipetable(which_table, 8*draw_xh    , draw_bottom_y   ,  3, 4*8, palace_wall_colors[44 * drawn_row + 33 + drawn_col]);
1908
                ptr_add_table(id_chtab_7_environmentwall, prandom(2) + 15, draw_xh    , 0, draw_bottom_y   , blitters_46h_mono_6, 0);
1909
        } else {
1910
                v3 = prandom(1);
1911
                v5 = prandom(4);
1912
                v2 = prandom(1);
1913
                v4 = prandom(4);
1914
                // store the background modifier for the current tile in a local variable
1915
                // apparently, for walls, the modifier stores whether there are adjacent walls
1916
                bg_modifier = curr_modifier & 0x7F;
1917
                switch (bg_modifier) {
1918
                        case WALL_MODIFIER_WWW:
1919
                                if (which_part != 0) {
1920
                                        if (prandom(4) == 0) {
1921
                                                ptr_add_table(RSET_WALL, RES_WALL_RNDBLOCK, draw_xh, 0, draw_bottom_y - 42, BLIT_NO_TRANS, 0);
1922
                                        }
1923
                                        ptr_add_table(RSET_WALL, RES_WALL_DIVIDER1 + v3, draw_xh + 1, v5, draw_bottom_y - 21, BLIT_TRANS, 0);
1924
                                }
1925
                                ptr_add_table(RSET_WALL, RES_WALL_DIVIDER1 + v2, draw_xh, v4, draw_bottom_y, BLIT_TRANS, 0);
1926
                                if (which_part != 0) {
1927
                                        if (is_dungeon) {
1928
                                                if (prandom(4) == 0) {
1929
                                                        draw_right_mark(prandom(3), v5);
1930
                                                }
1931
                                                if (prandom(4) == 0) {
1932
                                                        draw_left_mark(prandom(4), v5 - v3, v4 - v2);
1933
                                                }
1934
                                        }
1935
                                }
1936
                                break;
1937
                        case WALL_MODIFIER_SWS:
1938
                                if (is_dungeon) {
1939
                                        if (which_part != 0) {
1940
                                                if (prandom(6) == 0) {
1941
                                                        draw_left_mark(prandom(1), v5 - v3, v4 - v2);
1942
                                                }
1943
                                        }
1944
                                }
1945
                                break;
1946
                        case WALL_MODIFIER_SWW:
1947
                                if (which_part != 0) {
1948
                                        if (prandom(4) == 0) {
1949
                                                ptr_add_table(RSET_WALL, RES_WALL_RNDBLOCK, draw_xh, 0, draw_bottom_y - 42, BLIT_NO_TRANS, 0);
1950
                                        }
1951
                                        ptr_add_table(RSET_WALL, RES_WALL_DIVIDER1 + v3, draw_xh + 1 /*fix*/ , v5, draw_bottom_y - 21, BLIT_TRANS, 0);
1952
                                        if (is_dungeon) {
1953
                                                if (prandom(4) == 0) {
1954
                                                        draw_right_mark(prandom(3), v5);
1955
                                                }
1956
                                                if (prandom(4) == 0) {
1957
                                                        draw_left_mark(prandom(3), v5 - v3, v4 - v2);
1958
                                                }
1959
                                        }
1960
                                }
1961
                                break;
1962
                        case WALL_MODIFIER_WWS:
1963
                                if (which_part != 0) {
1964
                                        ptr_add_table(RSET_WALL, RES_WALL_DIVIDER1 + v3, draw_xh + 1, v5, draw_bottom_y - 21, BLIT_TRANS, 0);
1965
                                }
1966
                                ptr_add_table(RSET_WALL, RES_WALL_DIVIDER1 + v2, draw_xh, v4, draw_bottom_y, BLIT_TRANS, 0);
1967
                                if (which_part != 0) {
1968
                                        if (is_dungeon) {
1969
                                                if (prandom(4) == 0) {
1970
                                                        draw_right_mark(prandom(1) + 2, v5);
1971
                                                }
1972
                                                if (prandom(4) == 0) {
1973
                                                        draw_left_mark(prandom(4), v5 - v3, v4 - v2);
1974
                                                }
1975
                                        }
1976
                                }
1977
                                break;
1978
                }
1979
        }
1980
        random_seed = saved_prng_state;
1981
        ptr_add_table = saved_sim;
1982
}
1983
 
1984
void __pascal far draw_left_mark (word arg3, word arg2, word arg1) {
1985
        word lv1; word lv2;
1986
        static const word LPOS[] = {58, 41, 37, 20, 16};
1987
        lv1 = RES_WALL_MARK_TL;
1988
        lv2 = 0;
1989
        if (arg3 % 2) {
1990
                lv1 = RES_WALL_MARK_BL;
1991
        }
1992
        if (arg3 > 3) {
1993
                lv2 = arg1 + 6;
1994
        } else if (arg3 > 1) {
1995
                lv2 = arg2 + 6;
1996
        }
1997
        ptr_add_table(RSET_WALL, lv1, draw_xh + (arg3 == 2 || arg3 == 3), lv2, draw_bottom_y - LPOS[arg3], BLIT_TRANS, 0);
1998
}
1999
 
2000
void __pascal far draw_right_mark (word arg2, word arg1) {
2001
        word rv;
2002
        static const word RPOS[] = {52, 42, 31, 21};
2003
        rv = RES_WALL_MARK_TR;
2004
        if (arg2 % 2) {
2005
                rv = RES_WALL_MARK_BR;
2006
        }
2007
        if (arg2 < 2) {
2008
                arg1 = 24;
2009
        } else {
2010
                arg1 -= 3;
2011
        }
2012
        ptr_add_table(RSET_WALL, rv, draw_xh + (arg2 > 1), arg1, draw_bottom_y - RPOS[arg2], BLIT_TRANS, 0);
2013
}