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