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
#ifndef _MSC_VER // unistd.h does not exist in the Windows SDK.
24
#include <unistd.h>
25
#endif
26
#include <fcntl.h>
27
 
28
// data:4CB4
29
short cutscene_wait_frames;
30
// data:3D14
31
short cutscene_frame_time;
32
// data:588C
33
short disable_keys;
34
// data:436A
35
short hourglass_sandflow;
36
// data:5964
37
short hourglass_state;
38
// data:4CC4
39
short which_torch;
40
 
41
#pragma pack(push,1)
42
typedef struct hof_type {
43
        char name[25];
44
        short min,tick;
45
} hof_type;
46
SDL_COMPILE_TIME_ASSERT(hof_size, sizeof(hof_type) == 29);
47
#pragma pack(pop)
48
 
49
#define MAX_HOF_COUNT 6
50
// data:405E
51
short hof_count;
52
// data:589A
53
hof_type hof[MAX_HOF_COUNT];
54
 
55
#define N_STARS 6
56
 
57
// data:0D92
58
rect_type hof_rects[MAX_HOF_COUNT] = {
59
{ 84,   72,   96,  248},
60
{ 98,   72,  110,  248},
61
{112,   72,  124,  248},
62
{126,   72,  138,  248},
63
{140,   72,  152,  248},
64
{154,   72,  166,  248},
65
};
66
 
67
// seg001:0004
68
int __pascal far proc_cutscene_frame(int wait_frames) {
69
        cutscene_wait_frames = wait_frames;
70
        do {
71
                start_timer(timer_0, cutscene_frame_time);
72
                play_both_seq();
73
                draw_proom_drects(); // changed order of drects and flash
74
                if (flash_time) {
75
                        do_flash(flash_color);
76
                }
77
                if (flash_time) {
78
                        --flash_time;
79
                        remove_flash();
80
                }
81
                if (!check_sound_playing()) {
82
                        play_next_sound();
83
                }
84
                do {
85
                        if (!disable_keys && do_paused()) {
86
                                stop_sounds();
87
                                draw_rect(&screen_rect, 0);
88
#ifdef USE_FADE
89
                                if (is_global_fading) {
90
                                        fade_palette_buffer->proc_restore_free(fade_palette_buffer);
91
                                        is_global_fading = 0;
92
                                }
93
#endif
94
                                return 1;
95
                        }
96
#ifdef USE_FADE
97
                        if (is_global_fading) {
98
                                if (fade_palette_buffer->proc_fade_frame(fade_palette_buffer)) {
99
                                        fade_palette_buffer->proc_restore_free(fade_palette_buffer);
100
                                        is_global_fading = 0;
101
                                        return 2;
102
                                }
103
                        } else {
104
                                idle();
105
                        }
106
#else
107
                        idle();
108
#endif
109
                } while(!has_timer_stopped(0)); // busy waiting?
110
        } while(--cutscene_wait_frames);
111
        return 0;
112
}
113
 
114
// seg001:00DD
115
void __pascal far play_both_seq() {
116
        play_kid_seq();
117
        play_opp_seq();
118
}
119
 
120
// seg001:00E6
121
void __pascal far draw_proom_drects() {
122
        draw_princess_room_bg();
123
#ifdef USE_FADE
124
        if (!is_global_fading) {
125
#endif
126
        while (drects_count--) {
127
                copy_screen_rect(&drects[drects_count]);
128
        }
129
#ifdef USE_FADE
130
        }
131
#endif
132
        drects_count = 0;
133
        if (cutscene_wait_frames & 1) {
134
                draw_star(prandom(N_STARS - 1), 1);
135
        }
136
}
137
 
138
// seg001:0128
139
void __pascal far play_kid_seq() {
140
        loadkid();
141
        if (Char.frame) {
142
                play_seq();
143
                savekid();
144
        }
145
}
146
 
147
// seg001:013F
148
void __pascal far play_opp_seq() {
149
        loadshad_and_opp();
150
        if (Char.frame) {
151
                play_seq();
152
                saveshad();
153
        }
154
}
155
 
156
// seg001:0156
157
void __pascal far draw_princess_room_bg() {
158
        memset_near(table_counts, 0, sizeof(table_counts));
159
        loadkid();
160
        if (Char.frame) {
161
                load_frame_to_obj();
162
                obj_tilepos = 30;
163
                add_objtable(0);
164
        }
165
        loadshad();
166
        if (Char.frame) {
167
                load_frame_to_obj();
168
                obj_tilepos = 30;
169
                add_objtable(0);
170
        }
171
        redraw_needed_tiles();
172
        add_foretable(id_chtab_8_princessroom, 2 /*pillar piece*/, 30, 0, 167, blitters_10h_transp, 0);
173
        princess_room_torch();
174
        draw_hourglass();
175
        draw_tables();
176
}
177
 
178
// seg001:01E0
179
void __pascal far seqtbl_offset_shad_char(int seq_index) {
180
        loadshad();
181
        seqtbl_offset_char(seq_index);
182
        saveshad();
183
}
184
 
185
// seg001:01F9
186
void __pascal far seqtbl_offset_kid_char(int seq_index) {
187
        loadkid();
188
        seqtbl_offset_char(seq_index);
189
        savekid();
190
}
191
 
192
// seg001:0212
193
void __pascal far init_mouse_cu8() {
194
        init_mouse_go();
195
        Char.x = 144;
196
        seqtbl_offset_char(seq_106_mouse); // mouse
197
        play_seq();
198
}
199
 
200
// seg001:022A
201
void __pascal far init_mouse_go() {
202
        Char.charid = charid_24_mouse;
203
        Char.x = 199;
204
        Char.y = 167;
205
        Char.direction = dir_FF_left;
206
        seqtbl_offset_char(seq_105_mouse_forward); // mouse go
207
        play_seq();
208
}
209
 
210
// seg001:024D
211
void __pascal far princess_crouching() {
212
        init_princess();
213
        Char.x = 131;
214
        Char.y = 169;
215
        seqtbl_offset_char(seq_110_princess_crouching_PV2); // princess crouching [PV2]
216
        play_seq();
217
}
218
 
219
// seg001:026A
220
void __pascal far princess_stand() {
221
        init_princess_right();
222
        Char.x = 144;
223
        Char.y = 169;
224
        seqtbl_offset_char(seq_94_princess_stand_PV1); // princess stand [PV1]
225
        play_seq();
226
}
227
 
228
// seg001:0287
229
void __pascal far init_princess_x156() {
230
        init_princess();
231
        Char.x = 156;
232
}
233
 
234
// seg001:0291
235
void __pascal far princess_lying() {
236
        init_princess();
237
        Char.x = 92;
238
        Char.y = 162;
239
        seqtbl_offset_char(seq_103_princess_lying_PV2); // princess lying [PV2]
240
        play_seq();
241
}
242
 
243
// seg001:02AE
244
void __pascal far init_princess_right() {
245
        init_princess();
246
        Char.direction = dir_0_right;
247
}
248
 
249
// seg001:02B8
250
void __pascal far init_ending_princess() {
251
        init_princess();
252
        Char.x = 136;
253
        Char.y = 164;
254
        seqtbl_offset_char(seq_109_princess_stand_PV2); // princess standing [PV2]
255
        play_seq();
256
}
257
 
258
// seg001:02D5
259
void __pascal far init_mouse_1() {
260
        init_mouse_go();
261
        Char.x -= 2;
262
        Char.y = 164;
263
}
264
 
265
// seg001:02E4
266
void __pascal far init_princess() {
267
        Char.charid = charid_5_princess;
268
        Char.x = 120;
269
        Char.y = 166;
270
        Char.direction = dir_FF_left;
271
        seqtbl_offset_char(seq_94_princess_stand_PV1); // princess stand [PV1]
272
        play_seq();
273
}
274
 
275
// seg001:0307
276
void __pascal far init_vizier() {
277
        Char.charid = charid_6_vizier;
278
        Char.x = 198;
279
        Char.y = 166;
280
        Char.direction = dir_FF_left;
281
        seqtbl_offset_char(seq_95_Jaffar_stand_PV1); // Jaffar stand [PV1]
282
        play_seq();
283
}
284
 
285
// seg001:032A
286
void __pascal far init_ending_kid() {
287
        Char.charid = charid_0_kid;
288
        Char.x = 198;
289
        Char.y = 164;
290
        Char.direction = dir_FF_left;
291
        seqtbl_offset_char(seq_1_start_run); // start run
292
        play_seq();
293
}
294
 
295
// seg001:034D
296
void __pascal far cutscene_8() {
297
        play_sound(sound_35_cutscene_8_9); // cutscene 8, 9
298
        set_hourglass_state(hourglass_frame());
299
        init_mouse_cu8();
300
        savekid();
301
        princess_crouching();
302
        saveshad();
303
        if (fade_in_1()) return;
304
        if (proc_cutscene_frame(20)) return;
305
        seqtbl_offset_kid_char(seq_107_mouse_stand_up_and_go); // mouse stand up and go
306
        if (proc_cutscene_frame(20)) return;
307
        seqtbl_offset_shad_char(seq_111_princess_stand_up_PV2); // princess stand up [PV2]
308
        if (proc_cutscene_frame(20)) return;
309
        Kid.frame = 0;
310
        fade_out_1();
311
}
312
 
313
// seg001:03B7
314
void __pascal far cutscene_9() {
315
        play_sound(sound_35_cutscene_8_9); // cutscene 8, 9
316
        set_hourglass_state(hourglass_frame());
317
        princess_stand();
318
        saveshad();
319
        if (fade_in_1()) return;
320
        init_mouse_go();
321
        savekid();
322
        if (proc_cutscene_frame(5)) return;
323
        seqtbl_offset_shad_char(seq_112_princess_crouch_down_PV2); // princess crouch down [PV2]
324
        if (proc_cutscene_frame(9)) return;
325
        seqtbl_offset_kid_char(seq_114_mouse_stand); // mouse stand
326
        if (proc_cutscene_frame(58)) return;
327
        fade_out_1();
328
}
329
 
330
// seg001:041C
331
void __pascal far end_sequence_anim() {
332
        disable_keys = 1;
333
        if (!is_sound_on) {
334
                turn_sound_on_off(0x0F);
335
        }
336
        copy_screen_rect(&screen_rect);
337
        play_sound(sound_26_embrace); // arrived to princess
338
        init_ending_princess();
339
        saveshad();
340
        init_ending_kid();
341
        savekid();
342
        if (proc_cutscene_frame(8)) return;
343
        seqtbl_offset_shad_char(seq_108_princess_turn_and_hug); // princess turn and hug [PV2]
344
        if (proc_cutscene_frame(5)) return;
345
        seqtbl_offset_kid_char(seq_13_stop_run); // stop run
346
        if (proc_cutscene_frame(2)) return;
347
        Kid.frame = 0;
348
        if (proc_cutscene_frame(39)) return;
349
        init_mouse_1();
350
        savekid();
351
        if (proc_cutscene_frame(9)) return;
352
        seqtbl_offset_kid_char(seq_101_mouse_stands_up); // mouse stands up
353
        if (proc_cutscene_frame(41)) return;
354
        fade_out_1();
355
        while (check_sound_playing()) idle();
356
}
357
 
358
// seg001:04D3
359
void __pascal far time_expired() {
360
        disable_keys = 1;
361
        set_hourglass_state(7);
362
        hourglass_sandflow = -1;
363
        play_sound(sound_36_out_of_time); // time over
364
        if (fade_in_1()) return;
365
        if (proc_cutscene_frame(2)) return;
366
        if (proc_cutscene_frame(100)) return;
367
        fade_out_1();
368
        while (check_sound_playing()) {
369
                idle();
370
                do_paused();
371
        }
372
}
373
 
374
// seg001:0525
375
void __pascal far cutscene_12() {
376
        short var_2;
377
        var_2 = hourglass_frame();
378
        if (var_2 >= 6) {
379
                set_hourglass_state(var_2);
380
                init_princess_x156();
381
                saveshad();
382
                play_sound(sound_40_cutscene_12_short_time); // cutscene 12 short time
383
                if (fade_in_1()) return;
384
                if (proc_cutscene_frame(2)) return;
385
                seqtbl_offset_shad_char(98); // princess turn around [PV1]
386
                if (proc_cutscene_frame(24)) return;
387
                fade_out_1();
388
        } else {
389
                cutscene_2_6();
390
        }
391
}
392
 
393
// seg001:0584
394
void __pascal far cutscene_4() {
395
        play_sound(sound_27_cutscene_2_4_6_12); // cutscene 2, 4, 6, 12
396
        set_hourglass_state(hourglass_frame());
397
        princess_lying();
398
        saveshad();
399
        if (fade_in_1()) return;
400
        if (proc_cutscene_frame(26)) return;
401
        fade_out_1();
402
}
403
 
404
// seg001:05B8
405
void __pascal far cutscene_2_6() {
406
        play_sound(sound_27_cutscene_2_4_6_12); // cutscene 2, 4, 6, 12
407
        set_hourglass_state(hourglass_frame());
408
        init_princess_right();
409
        saveshad();
410
        if (fade_in_1()) return;
411
        if (proc_cutscene_frame(26)) return;
412
        fade_out_1();
413
}
414
 
415
// seg001:05EC
416
void __pascal far pv_scene() {
417
        init_princess();
418
        saveshad();
419
        if (fade_in_1()) return;
420
        init_vizier();
421
        savekid();
422
        if (proc_cutscene_frame(2)) return;
423
        play_sound(sound_50_story_2_princess); // story 2: princess waiting
424
        do {
425
                if (proc_cutscene_frame(1)) return;
426
                //idle();
427
        } while(check_sound_playing());
428
        cutscene_frame_time = 8;
429
        if (proc_cutscene_frame(5)) return;
430
        play_sound(sound_4_gate_closing); // gate closing
431
        do {
432
                if (proc_cutscene_frame(1)) return;
433
        } while(check_sound_playing());
434
        play_sound(sound_51_princess_door_opening); // princess door opening
435
        if (proc_cutscene_frame(3)) return;
436
        seqtbl_offset_shad_char(98); // princess turn around [PV1]
437
        if (proc_cutscene_frame(5)) return;
438
        seqtbl_offset_kid_char(96); // Jaffar walk [PV1]
439
        if (proc_cutscene_frame(6)) return;
440
        play_sound(sound_53_story_3_Jaffar_comes); // story 3: Jaffar comes
441
        seqtbl_offset_kid_char(97); // Jaffar stop [PV1]
442
        if (proc_cutscene_frame(4)) return;
443
        if (proc_cutscene_frame(18)) return;
444
        seqtbl_offset_kid_char(96); // Jaffar walk [PV1]
445
        if (proc_cutscene_frame(30)) return;
446
        seqtbl_offset_kid_char(97); // Jaffar stop [PV1]
447
        if (proc_cutscene_frame(35)) return;
448
        seqtbl_offset_kid_char(102); // Jaffar conjuring [PV1]
449
        cutscene_frame_time = 7;
450
        if (proc_cutscene_frame(1)) return;
451
        seqtbl_offset_shad_char(99); // princess step back [PV1]
452
        if (proc_cutscene_frame(17)) return;
453
        hourglass_state = 1;
454
        flash_time = 5;
455
        flash_color = 15; // white
456
        do {
457
                if (proc_cutscene_frame(1)) return;
458
                //idle();
459
        } while(check_sound_playing());
460
        seqtbl_offset_kid_char(100); // Jaffar end conjuring and walk [PV1]
461
        hourglass_sandflow = 0;
462
        if (proc_cutscene_frame(6)) return;
463
        play_sound(sound_52_story_4_Jaffar_leaves); // story 4: Jaffar leaves
464
        if (proc_cutscene_frame(24)) return;
465
        hourglass_state = 2;
466
        if (proc_cutscene_frame(9)) return;
467
        seqtbl_offset_shad_char(113); // princess look down [PV1]
468
        if (proc_cutscene_frame(28)) return;
469
        fade_out_1();
470
}
471
 
472
// seg001:07C7
473
void __pascal far set_hourglass_state(int state) {
474
        hourglass_sandflow = 0;
475
        hourglass_state = state;
476
}
477
 
478
// data:0DEC
479
short time_bound[] = {6, 17, 33, 65};
480
 
481
// seg001:07DA
482
int __pascal far hourglass_frame() {
483
        short bound_index;
484
        for (bound_index = 0; bound_index < 4; ++bound_index) {
485
                if (time_bound[bound_index] > rem_min) {
486
                        break;
487
                }
488
        }
489
        return 6 - bound_index;
490
}
491
 
492
// data:0DF4
493
short princess_torch_pos_xh[] = {11, 26};
494
// data:0DF8
495
short princess_torch_pos_xl[] = {5, 3};
496
// data:0DFC
497
short princess_torch_frame[] = {1, 6};
498
 
499
// seg001:0808
500
void __pascal far princess_room_torch() {
501
        short which;
502
        for (which = 2; which--; ) {
503
                which_torch = !which_torch;
504
                princess_torch_frame[which_torch] = get_torch_frame(princess_torch_frame[which_torch]);
505
                add_backtable(id_chtab_1_flameswordpotion, princess_torch_frame[which_torch] + 1, princess_torch_pos_xh[which_torch], princess_torch_pos_xl[which_torch], 116, 0, 0);
506
        }
507
}
508
 
509
// seg001:0863
510
void __pascal far draw_hourglass() {
511
        if (hourglass_sandflow >= 0) {
512
                hourglass_sandflow = (hourglass_sandflow + 1) % 3;
513
                if (hourglass_state >= 7) return;
514
                add_foretable(id_chtab_8_princessroom, hourglass_sandflow + 10, 20, 0, 164, blitters_10h_transp, 0);
515
        }
516
        if (hourglass_state) {
517
                add_midtable(id_chtab_8_princessroom, hourglass_state + 2, 19, 0, 168, blitters_10h_transp, 1);
518
        }
519
}
520
 
521
// seg001:08CA
522
void __pascal far reset_cutscene() {
523
        Guard.frame = 0;
524
        Kid.frame = 0;
525
        which_torch = 0;
526
        disable_keys = 0;
527
        hourglass_state = 0;
528
        // memset_near(byte_1ED6E, 0, 8); // not used elsewhere
529
        hourglass_sandflow = -1;
530
        cutscene_frame_time = 6;
531
        clear_tile_wipes();
532
        next_sound = -1;
533
}
534
 
535
// seg001:0908
536
void __pascal far do_flash(short color) {
537
        // stub
538
        if (color) {
539
                if (graphics_mode == gmMcgaVga) {
540
                        set_bg_attr(0, color);
541
                        if (color != 0) delay_ticks(2); // give some time to show the flash
542
                } else {
543
                        // ...
544
                }
545
        }
546
}
547
 
548
void delay_ticks(Uint32 ticks) {
549
#ifdef USE_REPLAY
550
        if (replaying && skipping_replay) return;
551
#endif
552
        SDL_Delay(ticks *(1000/60));
553
}
554
 
555
// This flashes the background with the color specified, but does not add delay to show the flash
556
void do_flash_no_delay(short color) {
557
        if (color) set_bg_attr(0, color);
558
}
559
 
560
// seg001:0981
561
void __pascal far remove_flash() {
562
        // stub
563
        if (graphics_mode == gmMcgaVga) {
564
                set_bg_attr(0, 0);
565
        } else {
566
                // ...
567
        }
568
}
569
 
570
// seg001:09D7
571
void __pascal far end_sequence() {
572
        peel_type* peel;
573
        short bgcolor;
574
        short color;
575
        rect_type rect;
576
        short hof_index;
577
        short i;
578
        color = 0;
579
        bgcolor = 15;
580
        load_intro(1, &end_sequence_anim, 1);
581
        clear_screen_and_sounds();
582
        load_opt_sounds(sound_56_ending_music, sound_56_ending_music); // winning theme
583
        play_sound_from_buffer(sound_pointers[sound_56_ending_music]); // winning theme
584
        if(offscreen_surface) free_surface(offscreen_surface); // missing in original
585
        offscreen_surface = make_offscreen_buffer(&screen_rect);
586
        load_title_images(0);
587
        current_target_surface = offscreen_surface;
588
        draw_image_2(0 /*story frame*/, chtab_title40, 0, 0, 0);
589
        draw_image_2(3 /*The tyrant Jaffar*/, chtab_title40, 24, 25, get_text_color(15, color_15_brightwhite, 0x800));
590
        fade_in_2(offscreen_surface, 0x800);
591
        pop_wait(timer_0, 900);
592
        start_timer(timer_0, 240);
593
        draw_image_2(0 /*main title image*/, chtab_title50, 0, 0, 0);
594
        transition_ltr();
595
        do_wait(timer_0);
596
        for (hof_index = 0; hof_index < hof_count; ++hof_index) {
597
                if (hof[hof_index].min < rem_min ||
598
                        (hof[hof_index].min == rem_min && hof[hof_index].tick < rem_tick)
599
                ) break;
600
        }
601
        if (hof_index < MAX_HOF_COUNT && hof_index <= hof_count) {
602
                fade_out_2(0x1000);
603
                for (i = 5; hof_index + 1 <= i; --i) {
604
                        hof[i] = hof[i - 1];
605
                }
606
                hof[i].name[0] = 0;
607
                hof[i].min = rem_min;
608
                hof[i].tick = rem_tick;
609
                if (hof_count < MAX_HOF_COUNT) {
610
                        ++hof_count;
611
                }
612
                draw_image_2(0 /*story frame*/, chtab_title40, 0, 0, 0);
613
                draw_image_2(3 /*Prince Of Persia*/, chtab_title50, 24, 24, blitters_10h_transp);
614
                show_hof();
615
                offset4_rect_add(&rect, &hof_rects[hof_index], -4, -1, -40, -1);
616
                peel = read_peel_from_screen(&rect);
617
                if (graphics_mode == gmMcgaVga) {
618
                        color = 0xBE;
619
                        bgcolor = 0xB7;
620
                }
621
                draw_rect(&rect, bgcolor);
622
                fade_in_2(offscreen_surface, 0x1800);
623
                current_target_surface = onscreen_surface_;
624
                while(input_str(&rect, hof[hof_index].name, 24, "", 0, 4, color, bgcolor) <= 0);
625
                restore_peel(peel);
626
                show_hof_text(&hof_rects[hof_index], -1, 0, hof[hof_index].name);
627
                hof_write();
628
                pop_wait(timer_0, 120);
629
                current_target_surface = offscreen_surface;
630
                draw_image_2(0 /*main title image*/, chtab_title50, 0, 0, blitters_0_no_transp);
631
                transition_ltr();
632
        }
633
        while (check_sound_playing() && !key_test_quit()) idle();
634
        fade_out_2(0x1000);
635
        start_level = -1;
636
        start_game();
637
}
638
 
639
// seg001:0C94
640
void __pascal far expired() {
641
        if (!demo_mode) {
642
                if(offscreen_surface) free_surface(offscreen_surface); // missing in original
643
                offscreen_surface = NULL;
644
                clear_screen_and_sounds();
645
                offscreen_surface = make_offscreen_buffer(&screen_rect);
646
                load_intro(1, &time_expired, 1);
647
        }
648
        start_level = -1;
649
        start_game();
650
}
651
 
652
// seg001:0CCD
653
void __pascal far load_intro(int which_imgs,cutscene_ptr_type func,int free_sounds) {
654
        short current_star;
655
        draw_rect(&screen_rect, 0);
656
        if (free_sounds) {
657
                free_optional_sounds();
658
        }
659
        free_all_chtabs_from(id_chtab_3_princessinstory);
660
        load_chtab_from_file(id_chtab_8_princessroom, 950, "PV.DAT", 1<<13);
661
        load_chtab_from_file(id_chtab_9_princessbed, 980, "PV.DAT", 1<<14);
662
        current_target_surface = offscreen_surface;
663
        method_6_blit_img_to_scr(get_image(id_chtab_8_princessroom, 0), 0, 0, 0);
664
        method_6_blit_img_to_scr(get_image(id_chtab_9_princessbed, 0), 0, 142, blitters_2_or);
665
 
666
        // Free the images that are not needed anymore.
667
        free_all_chtabs_from(id_chtab_9_princessbed);
668
        SDL_FreeSurface(get_image(id_chtab_8_princessroom, 0));
669
        if (NULL != chtab_addrs[id_chtab_8_princessroom]) chtab_addrs[id_chtab_8_princessroom]->images[0] = NULL;
670
 
671
        load_chtab_from_file(id_chtab_3_princessinstory, 800, "PV.DAT", 1<<9);
672
        load_chtab_from_file(id_chtab_4_jaffarinstory_princessincutscenes,
673
                             50*which_imgs + 850, "PV.DAT", 1<<10);
674
        for (current_star = 0; current_star < N_STARS; ++current_star) {
675
                draw_star(current_star, 0);
676
        }
677
        current_target_surface = onscreen_surface_;
678
        while (check_sound_playing()) {
679
                idle();
680
                do_paused();
681
        }
682
        need_drects = 1;
683
        reset_cutscene();
684
        is_cutscene = 1;
685
        func();
686
        is_cutscene = 0;
687
        free_all_chtabs_from(3);
688
        draw_rect(&screen_rect, 0);
689
}
690
 
691
typedef struct star_type {
692
        short x,y,color;
693
} star_type;
694
 
695
// data:0DC2
696
star_type stars[N_STARS] = {
697
        {20, 97,0},
698
        {16,104,1},
699
        {23,110,2},
700
        {17,116,3},
701
        {24,120,4},
702
        {18,128,0},
703
};
704
#define N_STAR_COLORS 5
705
// data:0DE6
706
const byte star_colors[N_STAR_COLORS] = {8, 7, 15, 15, 7};
707
 
708
// seg001:0E1C
709
void __pascal far draw_star(int which_star,int mark_dirty) {
710
        // The stars in the window of the princess's room.
711
        rect_type rect;
712
        short star_color;
713
        star_color = 15;
714
        rect.right = rect.left = stars[which_star].x;
715
        ++rect.right;
716
        rect.bottom = rect.top = stars[which_star].y;
717
        ++rect.bottom;
718
        if (graphics_mode != gmCga && graphics_mode != gmHgaHerc) {
719
                stars[which_star].color = (stars[which_star].color + 1) % N_STAR_COLORS;
720
                star_color = star_colors[stars[which_star].color];
721
        }
722
        draw_rect(&rect, star_color);
723
        if (mark_dirty) {
724
                add_drect(&rect);
725
        }
726
}
727
 
728
// seg001:0E94
729
void __pascal far show_hof() {
730
        // Hall of Fame
731
        short index;
732
        char time_text[12];
733
        for (index = 0; index < hof_count; ++index) {
734
 
735
#ifdef ALLOW_INFINITE_TIME
736
                int minutes, seconds;
737
                if (hof[index].min > 0) {
738
                        minutes = hof[index].min - 1;
739
                        seconds = hof[index].tick / 12;
740
                } else {
741
                        // negative minutes means time ran 'forward' from 0:00 upwards
742
                        minutes = abs(hof[index].min) - 1;
743
                        seconds = (719 - hof[index].tick) / 12;
744
                }
745
                snprintf(time_text, sizeof(time_text), "%d:%02d", minutes, seconds);
746
#else
747
                snprintf(time_text, sizeof(time_text), "%d:%02d", hof[index].min - 1, hof[index].tick / 12);
748
#endif
749
 
750
                show_hof_text(&hof_rects[index], -1, 0, hof[index].name);
751
                show_hof_text(&hof_rects[index], 1, 0, time_text);
752
        }
753
        // stub
754
}
755
 
756
static const char* hof_file = "PRINCE.HOF";
757
 
758
const char* get_hof_path(char* custom_path_buffer, size_t max_len) {
759
        if (!use_custom_levelset) {
760
                return hof_file;
761
        }
762
        // if playing a custom levelset, try to use the mod folder
763
        snprintf(custom_path_buffer, max_len, "mods/%s/%s", levelset_name, hof_file /*PRINCE.HOF*/ );
764
        return custom_path_buffer;
765
}
766
 
767
// seg001:0F17
768
void __pascal far hof_write() {
769
        int handle;
770
        char custom_hof_path[POP_MAX_PATH];
771
        const char* hof_path = get_hof_path(custom_hof_path, sizeof(custom_hof_path));
772
        // no O_TRUNC
773
        handle = open(hof_path, O_WRONLY | O_CREAT | O_BINARY, 0600);
774
        if (handle < 0 ||
775
            write(handle, &hof_count, 2) != 2 ||
776
            write(handle, &hof, sizeof(hof)) != sizeof(hof) ||
777
            close(handle))
778
                perror(hof_path);
779
        if (handle >= 0)
780
                close(handle);
781
}
782
 
783
// seg001:0F6C
784
void __pascal far hof_read() {
785
        int handle;
786
        hof_count = 0;
787
        char custom_hof_path[POP_MAX_PATH];
788
        const char* hof_path = get_hof_path(custom_hof_path, sizeof(custom_hof_path));
789
        handle = open(hof_path, O_RDONLY | O_BINARY);
790
        if (handle < 0)
791
                return;
792
        if (read(handle, &hof_count, 2) != 2 ||
793
            read(handle, &hof, sizeof(hof)) != sizeof(hof)) {
794
                perror(hof_path);
795
                hof_count = 0;
796
        }
797
        close(handle);
798
}
799
 
800
// seg001:0FC3
801
void __pascal far show_hof_text(rect_type far *rect,int x_align,int y_align, const char *text) {
802
        short shadow_color;
803
        short text_color;
804
        rect_type rect2;
805
        text_color = 15;
806
        shadow_color = 0;
807
        if (graphics_mode == gmMcgaVga) {
808
                text_color = 0xB7;
809
        }
810
        offset2_rect(&rect2, rect, 1, 1);
811
        show_text_with_color(&rect2, x_align, y_align, text, shadow_color);
812
        show_text_with_color(rect, x_align, y_align, text, text_color);
813
}
814
 
815
// seg001:1029
816
int __pascal far fade_in_1() {
817
#ifdef USE_FADE
818
//      sbyte index;
819
        word interrupted;
820
        if (graphics_mode == gmMcgaVga) {
821
                fade_palette_buffer = make_pal_buffer_fadein(offscreen_surface, 0x6689, /*0*/ 2);
822
                is_global_fading = 1;
823
                do {
824
                        interrupted = proc_cutscene_frame(1);
825
                        if (interrupted == 1) {
826
                                return 1;
827
                        }
828
                } while (interrupted == 0);
829
                is_global_fading = 0;
830
        } else {
831
                // ...
832
        }
833
        return 0;
834
#else
835
        // stub
836
        method_1_blit_rect(onscreen_surface_, offscreen_surface, &screen_rect, &screen_rect, 0);
837
        updateScreen();
838
//      SDL_UpdateRect(onscreen_surface_, 0, 0, 0, 0); // debug
839
        return 0;
840
#endif
841
}
842
 
843
// seg001:112D
844
int __pascal far fade_out_1() {
845
#ifdef USE_FADE
846
        word interrupted;
847
        if (graphics_mode == gmMcgaVga) {
848
                fade_palette_buffer = make_pal_buffer_fadeout(0x6689, /*0*/ 2);
849
                is_global_fading = 1;
850
                do {
851
                        interrupted = proc_cutscene_frame(1);
852
                        if (interrupted == 1) {
853
                                return 1;
854
                        }
855
                } while (interrupted == 0);
856
                is_global_fading = 0;
857
        } else {
858
                // ...
859
        }
860
#endif
861
        // stub
862
        return 0;
863
}