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 | } |