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 | #include <setjmp.h> |
||
23 | #include <math.h> |
||
24 | |||
25 | // data:461E |
||
26 | dat_type * dathandle; |
||
27 | |||
28 | // data:4C08 |
||
29 | word need_redraw_because_flipped; |
||
30 | |||
31 | // seg000:0000 |
||
32 | void far pop_main() { |
||
33 | const char* temp = check_param("seed="); |
||
34 | if (temp != NULL) { |
||
35 | random_seed = atoi(temp+5); |
||
36 | seed_was_init = 1; |
||
37 | } |
||
38 | |||
39 | // debug only: check that the sequence table deobfuscation did not mess things up |
||
40 | #ifdef CHECK_SEQTABLE_MATCHES_ORIGINAL |
||
41 | check_seqtable_matches_original(); |
||
42 | #endif |
||
43 | |||
44 | load_global_options(); |
||
45 | |||
46 | #ifdef USE_REPLAY |
||
47 | if (g_argc > 1) { |
||
48 | char *filename = g_argv[1]; // file dragged on top of executable or double clicked |
||
49 | char *e = strrchr(filename, '.'); |
||
50 | if (e != NULL && strcasecmp(e, ".P1R") == 0) { // valid replay filename passed as first arg |
||
51 | start_with_replay_file(filename); |
||
52 | } |
||
53 | } |
||
54 | |||
55 | temp = check_param("validate"); |
||
56 | if (temp != NULL) { |
||
57 | is_validate_mode = 1; |
||
58 | start_with_replay_file(temp); |
||
59 | } |
||
60 | #endif |
||
61 | |||
62 | check_mod_param(); |
||
63 | load_mod_options(); |
||
64 | |||
65 | // CusPop option |
||
66 | is_blind_mode = start_in_blind_mode; |
||
67 | // Bug: with start_in_blind_mode enabled, moving objects are not displayed until blind mode is toggled off+on?? |
||
68 | |||
69 | apply_seqtbl_patches(); |
||
70 | |||
71 | char sprintf_temp[100]; |
||
72 | int i; |
||
73 | |||
74 | dathandle = open_dat("PRINCE.DAT", 0); |
||
75 | |||
76 | /*video_mode =*/ parse_grmode(); |
||
77 | |||
78 | init_timer(60); |
||
79 | parse_cmdline_sound(); |
||
80 | |||
81 | set_hc_pal(); |
||
82 | |||
83 | current_target_surface = rect_sthg(onscreen_surface_, &screen_rect); |
||
84 | show_loading(); |
||
85 | set_joy_mode(); |
||
86 | cheats_enabled = check_param("megahit") != NULL; |
||
87 | #ifdef USE_DEBUG_CHEATS |
||
88 | debug_cheats_enabled = check_param("debug") != NULL; |
||
89 | if (debug_cheats_enabled) cheats_enabled = 1; // param 'megahit' not necessary if 'debug' is used |
||
90 | #endif |
||
91 | draw_mode = check_param("draw") != NULL && cheats_enabled; |
||
92 | demo_mode = check_param("demo") != NULL; |
||
93 | |||
94 | init_copyprot_dialog(); |
||
95 | #ifdef USE_REPLAY |
||
96 | init_record_replay(); |
||
97 | #endif |
||
98 | |||
99 | if (cheats_enabled |
||
100 | #ifdef USE_REPLAY |
||
101 | || recording |
||
102 | #endif |
||
103 | ) { |
||
104 | for (i = 15; i >= 0; --i) { |
||
105 | snprintf(sprintf_temp, sizeof(sprintf_temp), "%d", i); |
||
106 | if (check_param(sprintf_temp)) { |
||
107 | start_level = i; |
||
108 | break; |
||
109 | } |
||
110 | } |
||
111 | } |
||
112 | #ifdef USE_SCREENSHOT |
||
113 | init_screenshot(); |
||
114 | #endif |
||
115 | |||
116 | init_game_main(); |
||
117 | } |
||
118 | |||
119 | byte* level_var_palettes; |
||
120 | |||
121 | // seg000:024F |
||
122 | void __pascal far init_game_main() { |
||
123 | doorlink1_ad = /*&*/level.doorlinks1; |
||
124 | doorlink2_ad = /*&*/level.doorlinks2; |
||
125 | prandom(1); |
||
126 | if (graphics_mode == gmMcgaVga) { |
||
127 | // Guard palettes |
||
128 | guard_palettes = (byte*) load_from_opendats_alloc(10, "bin", NULL, NULL); |
||
129 | // (blood, hurt flash) #E00030 = red |
||
130 | set_pal(12, 0x38, 0x00, 0x0C, 1); |
||
131 | // (palace wall pattern) #C09850 = light brown |
||
132 | set_pal( 6, 0x30, 0x26, 0x14, 0); |
||
133 | |||
134 | // Level color variations (1.3) |
||
135 | level_var_palettes = load_from_opendats_alloc(20, "bin", NULL, NULL); |
||
136 | } |
||
137 | // PRINCE.DAT: sword |
||
138 | chtab_addrs[id_chtab_0_sword] = load_sprites_from_file(700, 1<<2, 1); |
||
139 | // PRINCE.DAT: flame, sword on floor, potion |
||
140 | chtab_addrs[id_chtab_1_flameswordpotion] = load_sprites_from_file(150, 1<<3, 1); |
||
141 | close_dat(dathandle); |
||
142 | #ifdef USE_LIGHTING |
||
143 | init_lighting(); |
||
144 | #endif |
||
145 | load_sounds(0, 43); |
||
146 | load_opt_sounds(43, 56); //added |
||
147 | hof_read(); |
||
148 | show_splash(); // added |
||
149 | show_use_fixes_and_enhancements_prompt(); // added |
||
150 | start_game(); |
||
151 | } |
||
152 | |||
153 | |||
154 | // data:02C2 |
||
155 | word first_start = 1; |
||
156 | // data:4C38 |
||
157 | jmp_buf setjmp_buf; |
||
158 | // seg000:0358 |
||
159 | void __pascal far start_game() { |
||
160 | #ifdef USE_COPYPROT |
||
161 | word which_entry; |
||
162 | word pos; |
||
163 | word entry_used[40]; |
||
164 | byte letts_used[26]; |
||
165 | #endif |
||
166 | screen_updates_suspended = 0; |
||
167 | // Prevent filling of stack. |
||
168 | // start_game is called from many places to restart the game, for example: |
||
169 | // process_key, play_frame, draw_game_frame, play_level, control_kid, end_sequence, expired |
||
170 | if (first_start) { |
||
171 | first_start = 0; |
||
172 | setjmp(/*&*/setjmp_buf); |
||
173 | } else { |
||
174 | draw_rect(&screen_rect, 0); |
||
175 | show_quotes(); |
||
176 | clear_screen_and_sounds(); |
||
177 | longjmp(/*&*/setjmp_buf,-1); |
||
178 | } |
||
179 | release_title_images(); // added |
||
180 | free_optsnd_chtab(); // added |
||
181 | #ifdef USE_COPYPROT |
||
182 | copyprot_plac = prandom(13); |
||
183 | memset(&entry_used, 0, sizeof(entry_used)); |
||
184 | memset(&letts_used, 0, sizeof(letts_used)); |
||
185 | for (pos = 0; pos < 14; ++pos) { |
||
186 | do { |
||
187 | if (pos == copyprot_plac) { |
||
188 | which_entry = copyprot_idx = prandom(39); |
||
189 | } else { |
||
190 | which_entry = prandom(39); |
||
191 | } |
||
192 | } while (entry_used[which_entry] || letts_used[copyprot_letter[which_entry]-'A']); |
||
193 | cplevel_entr[pos] = which_entry; |
||
194 | entry_used[which_entry] = 1; |
||
195 | letts_used[copyprot_letter[which_entry]-'A'] = 1; |
||
196 | } |
||
197 | #endif |
||
198 | if (skip_title) { // CusPop option: skip the title sequence (level loads instantly) |
||
199 | int level_number = (start_level >= 0) ? start_level : first_level; |
||
200 | init_game(level_number); |
||
201 | return; |
||
202 | } |
||
203 | |||
204 | if (start_level < 0) { |
||
205 | show_title(); |
||
206 | } else { |
||
207 | init_game(start_level); |
||
208 | } |
||
209 | } |
||
210 | |||
211 | #ifdef USE_QUICKSAVE |
||
212 | // All these functions return true on success, false otherwise. |
||
213 | |||
214 | FILE* quick_fp; |
||
215 | |||
216 | int process_save(void* data, size_t data_size) { |
||
217 | return fwrite(data, data_size, 1, quick_fp) == 1; |
||
218 | } |
||
219 | |||
220 | int process_load(void* data, size_t data_size) { |
||
221 | return fread(data, data_size, 1, quick_fp) == 1; |
||
222 | } |
||
223 | |||
224 | typedef int process_func_type(void* data, size_t data_size); |
||
225 | |||
226 | int quick_process(process_func_type process_func) { |
||
227 | int ok = 1; |
||
228 | #define process(x) ok = ok && process_func(&(x), sizeof(x)) |
||
229 | // level |
||
230 | process(level); |
||
231 | process(checkpoint); |
||
232 | process(upside_down); |
||
233 | process(drawn_room); |
||
234 | process(current_level); |
||
235 | process(next_level); |
||
236 | process(mobs_count); |
||
237 | process(mobs); |
||
238 | process(trobs_count); |
||
239 | process(trobs); |
||
240 | process(leveldoor_open); |
||
241 | //process(exit_room_timer); |
||
242 | // kid |
||
243 | process(Kid); |
||
244 | process(hitp_curr); |
||
245 | process(hitp_max); |
||
246 | process(hitp_beg_lev); |
||
247 | process(grab_timer); |
||
248 | process(holding_sword); |
||
249 | process(united_with_shadow); |
||
250 | process(have_sword); |
||
251 | /*process(ctrl1_forward); |
||
252 | process(ctrl1_backward); |
||
253 | process(ctrl1_up); |
||
254 | process(ctrl1_down); |
||
255 | process(ctrl1_shift2);*/ |
||
256 | process(kid_sword_strike); |
||
257 | process(pickup_obj_type); |
||
258 | process(offguard); |
||
259 | // guard |
||
260 | process(Guard); |
||
261 | process(Char); |
||
262 | process(Opp); |
||
263 | process(guardhp_curr); |
||
264 | process(guardhp_max); |
||
265 | process(demo_index); |
||
266 | process(demo_time); |
||
267 | process(curr_guard_color); |
||
268 | process(guard_notice_timer); |
||
269 | process(guard_skill); |
||
270 | process(shadow_initialized); |
||
271 | process(guard_refrac); |
||
272 | process(justblocked); |
||
273 | process(droppedout); |
||
274 | // collision |
||
275 | process(curr_row_coll_room); |
||
276 | process(curr_row_coll_flags); |
||
277 | process(below_row_coll_room); |
||
278 | process(below_row_coll_flags); |
||
279 | process(above_row_coll_room); |
||
280 | process(above_row_coll_flags); |
||
281 | process(prev_collision_row); |
||
282 | // flash |
||
283 | process(flash_color); |
||
284 | process(flash_time); |
||
285 | // sounds |
||
286 | process(need_level1_music); |
||
287 | process(is_screaming); |
||
288 | process(is_feather_fall); |
||
289 | process(last_loose_sound); |
||
290 | //process(next_sound); |
||
291 | //process(current_sound); |
||
292 | // random |
||
293 | process(random_seed); |
||
294 | // remaining time |
||
295 | process(rem_min); |
||
296 | process(rem_tick); |
||
297 | // saved controls |
||
298 | process(control_x); |
||
299 | process(control_y); |
||
300 | process(control_shift); |
||
301 | process(control_forward); |
||
302 | process(control_backward); |
||
303 | process(control_up); |
||
304 | process(control_down); |
||
305 | process(control_shift2); |
||
306 | process(ctrl1_forward); |
||
307 | process(ctrl1_backward); |
||
308 | process(ctrl1_up); |
||
309 | process(ctrl1_down); |
||
310 | process(ctrl1_shift2); |
||
311 | #undef process |
||
312 | return ok; |
||
313 | } |
||
314 | |||
315 | const char* quick_file = "QUICKSAVE.SAV"; |
||
316 | const char quick_version[] = "V1.16b4 "; |
||
317 | char quick_control[] = "........"; |
||
318 | #ifdef OSX |
||
319 | #include <CoreServices/CoreServices.h> |
||
320 | #endif // OSX |
||
321 | |||
322 | const char* get_quick_path(char* custom_path_buffer, size_t max_len) { |
||
323 | if (!use_custom_levelset) { |
||
324 | #ifdef OSX |
||
325 | static char path[PATH_MAX] = ""; |
||
326 | if (path[0] == 0) |
||
327 | { |
||
328 | FSRef ref; |
||
329 | FSFindFolder (kUserDomain, kApplicationSupportFolderType, kCreateFolder, &ref); |
||
330 | FSRefMakePath (&ref, (UInt8 *) &path, PATH_MAX); |
||
331 | strcat (path, "/Prince of Persia"); |
||
332 | mkdir (path, 0755); |
||
333 | strcat (path, "/QUICKSAVE.SAV"); |
||
334 | } |
||
335 | return (path); |
||
336 | #else // !OSX |
||
337 | return quick_file; |
||
338 | #endif // OSX |
||
339 | } |
||
340 | // if playing a custom levelset, try to use the mod folder |
||
341 | snprintf(custom_path_buffer, max_len, "mods/%s/%s", levelset_name, quick_file /*QUICKSAVE.SAV*/ ); |
||
342 | return custom_path_buffer; |
||
343 | } |
||
344 | |||
345 | int quick_save() { |
||
346 | int ok = 0; |
||
347 | char custom_quick_path[POP_MAX_PATH]; |
||
348 | const char* path = get_quick_path(custom_quick_path, sizeof(custom_quick_path)); |
||
349 | quick_fp = fopen(path, "wb"); |
||
350 | if (quick_fp != NULL) { |
||
351 | process_save((void*) quick_version, COUNT(quick_version)); |
||
352 | ok = quick_process(process_save); |
||
353 | fclose(quick_fp); |
||
354 | quick_fp = NULL; |
||
355 | } |
||
356 | return ok; |
||
357 | } |
||
358 | |||
359 | void restore_room_after_quick_load() { |
||
360 | int temp1 = curr_guard_color; |
||
361 | int temp2 = next_level; |
||
362 | reset_level_unused_fields(false); |
||
363 | load_lev_spr(current_level); |
||
364 | curr_guard_color = temp1; |
||
365 | next_level = temp2; |
||
366 | |||
367 | //need_full_redraw = 1; |
||
368 | different_room = 1; |
||
369 | next_room = drawn_room; |
||
370 | load_room_links(); |
||
371 | //draw_level_first(); |
||
372 | //gen_palace_wall_colors(); |
||
373 | is_guard_notice = 0; // prevent guard turning around immediately |
||
374 | draw_game_frame(); // for falling |
||
375 | //redraw_screen(1); // for room_L |
||
376 | |||
377 | hitp_delta = guardhp_delta = 1; // force HP redraw |
||
378 | draw_hp(); |
||
379 | loadkid_and_opp(); |
||
380 | // Get rid of "press button" message if kid was dead before quickload. |
||
381 | text_time_total = text_time_remaining = 0; |
||
382 | //next_sound = current_sound = -1; |
||
383 | exit_room_timer = 0; |
||
384 | } |
||
385 | |||
386 | int quick_load() { |
||
387 | int ok = 0; |
||
388 | char custom_quick_path[POP_MAX_PATH]; |
||
389 | const char* path = get_quick_path(custom_quick_path, sizeof(custom_quick_path)); |
||
390 | quick_fp = fopen(path, "rb"); |
||
391 | if (quick_fp != NULL) { |
||
392 | // check quicksave version is compatible |
||
393 | process_load(quick_control, COUNT(quick_control)); |
||
394 | if (strcmp(quick_control, quick_version) != 0) { |
||
395 | fclose(quick_fp); |
||
396 | quick_fp = NULL; |
||
397 | return 0; |
||
398 | } |
||
399 | |||
400 | stop_sounds(); |
||
401 | start_timer(timer_0, 5); // briefly display a black screen as a visual cue |
||
402 | draw_rect(&screen_rect, 0); |
||
403 | screen_updates_suspended = 0; |
||
404 | request_screen_update(); |
||
405 | screen_updates_suspended = 1; |
||
406 | short old_rem_min = rem_min; |
||
407 | word old_rem_tick = rem_tick; |
||
408 | |||
409 | ok = quick_process(process_load); |
||
410 | fclose(quick_fp); |
||
411 | quick_fp = NULL; |
||
412 | |||
413 | restore_room_after_quick_load(); |
||
414 | |||
415 | do_wait(timer_0); |
||
416 | screen_updates_suspended = 0; |
||
417 | request_screen_update(); |
||
418 | |||
419 | #ifdef USE_QUICKLOAD_PENALTY |
||
420 | // Subtract one minute from the remaining time (if it is above 5 minutes) |
||
421 | if (enable_quicksave_penalty && |
||
422 | // don't apply the penalty after time has already stopped! |
||
423 | (current_level < 13 || (current_level == 13 && leveldoor_open < 2)) |
||
424 | ) { |
||
425 | int ticks_elapsed = 720 * (rem_min - old_rem_min) + (rem_tick - old_rem_tick); |
||
426 | // don't restore time at all if the elapsed time is between 0 and 1 minutes |
||
427 | if (ticks_elapsed > 0 && ticks_elapsed < 720) { |
||
428 | rem_min = old_rem_min; |
||
429 | rem_tick = old_rem_tick; |
||
430 | } |
||
431 | else { |
||
432 | if (rem_min == 6) rem_tick = 719; // crop to "5 minutes" exactly, if hitting the threshold in <1 minute |
||
433 | if (rem_min > 5 /*be lenient, not much time left*/ || rem_min < 0 /*time runs 'forward' if < 0*/) { |
||
434 | --rem_min; |
||
435 | } |
||
436 | } |
||
437 | |||
438 | } |
||
439 | #endif |
||
440 | } |
||
441 | return ok; |
||
442 | } |
||
443 | |||
444 | int need_quick_save = 0; |
||
445 | int need_quick_load = 0; |
||
446 | |||
447 | void check_quick_op() { |
||
448 | if (!enable_quicksave) return; |
||
449 | if (need_quick_save) { |
||
450 | if (!is_feather_fall && quick_save()) { |
||
451 | display_text_bottom("GAME SAVED"); |
||
452 | } else { |
||
453 | display_text_bottom("UNABLE TO SAVE GAME"); |
||
454 | } |
||
455 | need_quick_save = 0; |
||
456 | text_time_total = 24; |
||
457 | text_time_remaining = 24; |
||
458 | } |
||
459 | if (need_quick_load) { |
||
460 | #ifdef USE_REPLAY |
||
461 | if (recording) { |
||
462 | stop_recording(); // quickloading would mess up the replay! |
||
463 | } |
||
464 | #endif |
||
465 | if (quick_load()) { |
||
466 | display_text_bottom("GAME LOADED"); |
||
467 | } else { |
||
468 | display_text_bottom("NO SAVEGAME AVAILABLE"); |
||
469 | } |
||
470 | need_quick_load = 0; |
||
471 | text_time_total = 24; |
||
472 | text_time_remaining = 24; |
||
473 | } |
||
474 | } |
||
475 | |||
476 | |||
477 | #endif // USE_QUICKSAVE |
||
478 | |||
479 | Uint32 temp_shift_release_callback(Uint32 interval, void *param) { |
||
480 | const Uint8* state = SDL_GetKeyboardState(NULL); |
||
481 | if (state[SDL_SCANCODE_LSHIFT]) key_states[SDL_SCANCODE_LSHIFT] = 1; |
||
482 | if (state[SDL_SCANCODE_RSHIFT]) key_states[SDL_SCANCODE_RSHIFT] = 1; |
||
483 | return 0; // causes the timer to be removed |
||
484 | } |
||
485 | |||
486 | // seg000:04CD |
||
487 | int __pascal far process_key() { |
||
488 | char sprintf_temp[80]; |
||
489 | int key; |
||
490 | const char* answer_text = NULL; |
||
491 | word need_show_text; |
||
492 | need_show_text = 0; |
||
493 | key = key_test_quit(); |
||
494 | |||
495 | if (start_level < 0) { |
||
496 | if (key || control_shift) { |
||
497 | #ifdef USE_QUICKSAVE |
||
498 | if (key == SDL_SCANCODE_F9) need_quick_load = 1; |
||
499 | #endif |
||
500 | #ifdef USE_REPLAY |
||
501 | if (key == SDL_SCANCODE_TAB || need_start_replay) { |
||
502 | start_replay(); |
||
503 | } |
||
504 | else if (key == (SDL_SCANCODE_TAB | WITH_CTRL)) { |
||
505 | start_level = first_level; |
||
506 | start_recording(); |
||
507 | } else |
||
508 | #endif |
||
509 | if (key == (SDL_SCANCODE_L | WITH_CTRL)) { // ctrl-L |
||
510 | if (!load_game()) return 0; |
||
511 | } else { |
||
512 | start_level = first_level; // 1 |
||
513 | } |
||
514 | draw_rect(&screen_rect, 0); |
||
515 | #ifdef USE_FADE |
||
516 | if (is_global_fading) { |
||
517 | fade_palette_buffer->proc_restore_free(fade_palette_buffer); |
||
518 | is_global_fading = 0; |
||
519 | } |
||
520 | #endif |
||
521 | start_game(); |
||
522 | } |
||
523 | } |
||
524 | // If the Kid died, enter or shift will restart the level. |
||
525 | if (rem_min != 0 && Kid.alive > 6 && (control_shift || key == SDL_SCANCODE_RETURN)) { |
||
526 | key = SDL_SCANCODE_A | WITH_CTRL; // ctrl-a |
||
527 | } |
||
528 | #ifdef USE_REPLAY |
||
529 | if (recording) key_press_while_recording(&key); |
||
530 | else if (replaying) key_press_while_replaying(&key); |
||
531 | #endif |
||
532 | if (key == 0) return 0; |
||
533 | if (is_keyboard_mode) clear_kbd_buf(); |
||
534 | |||
535 | if (!cheats_enabled) // Pierre-Marie Baty -- allow typing 'megahit' in game to enable cheats |
||
536 | { |
||
537 | static const int megahit_chars[] = { SDL_SCANCODE_M, SDL_SCANCODE_E, SDL_SCANCODE_G, SDL_SCANCODE_A, SDL_SCANCODE_H, SDL_SCANCODE_I, SDL_SCANCODE_T }; |
||
538 | static int megahit_index = 0; |
||
539 | megahit_index = (key == megahit_chars[megahit_index] ? megahit_index + 1 : 0); |
||
540 | if (megahit_index == sizeof (megahit_chars) / sizeof (megahit_chars[0])) |
||
541 | { |
||
542 | answer_text = "CHEATS ENABLED"; |
||
543 | need_show_text = 1; |
||
544 | cheats_enabled = 1; |
||
545 | } |
||
546 | } |
||
547 | |||
548 | switch(key) { |
||
549 | case SDL_SCANCODE_ESCAPE: // esc |
||
550 | case SDL_SCANCODE_ESCAPE | WITH_SHIFT: // allow pause while grabbing |
||
551 | is_paused = 1; |
||
552 | break; |
||
553 | case SDL_SCANCODE_SPACE: // space |
||
554 | is_show_time = 1; |
||
555 | break; |
||
556 | case SDL_SCANCODE_A | WITH_CTRL: // ctrl-a |
||
557 | if (current_level != 15) { |
||
558 | stop_sounds(); |
||
559 | is_restart_level = 1; |
||
560 | } |
||
561 | break; |
||
562 | case SDL_SCANCODE_G | WITH_CTRL: // ctrl-g |
||
563 | // CusPoP: first and last level where saving is allowed |
||
564 | // if (current_level > 2 && current_level < 14) { // original |
||
565 | if (current_level >= saving_allowed_first_level && current_level <= saving_allowed_last_level) { |
||
566 | save_game(); |
||
567 | } |
||
568 | break; |
||
569 | case SDL_SCANCODE_J | WITH_CTRL: // ctrl-j |
||
570 | if ((sound_flags & sfDigi) && sound_mode == smTandy) { |
||
571 | answer_text = "JOYSTICK UNAVAILABLE"; |
||
572 | } else { |
||
573 | if (set_joy_mode()) { |
||
574 | answer_text = "JOYSTICK MODE"; |
||
575 | } else { |
||
576 | answer_text = "JOYSTICK NOT FOUND"; |
||
577 | } |
||
578 | } |
||
579 | need_show_text = 1; |
||
580 | break; |
||
581 | case SDL_SCANCODE_K | WITH_CTRL: // ctrl-k |
||
582 | answer_text = "KEYBOARD MODE"; |
||
583 | is_joyst_mode = 0; |
||
584 | is_keyboard_mode = 1; |
||
585 | need_show_text = 1; |
||
586 | break; |
||
587 | case SDL_SCANCODE_R | WITH_CTRL: // ctrl-r |
||
588 | start_level = -1; |
||
589 | start_game(); |
||
590 | break; |
||
591 | case SDL_SCANCODE_S | WITH_CTRL: // ctrl-s |
||
592 | turn_sound_on_off((!is_sound_on) * 15); |
||
593 | answer_text = "SOUND OFF"; |
||
594 | if (is_sound_on) { |
||
595 | answer_text = "SOUND ON"; |
||
596 | } |
||
597 | // |
||
598 | need_show_text = 1; |
||
599 | break; |
||
600 | case SDL_SCANCODE_V | WITH_CTRL: // ctrl-v |
||
601 | //answer_text = "PRINCE OF PERSIA V1.0"; |
||
602 | snprintf(sprintf_temp, sizeof(sprintf_temp), "Prince of Persia v%s-SDL\n", SDLPOP_VERSION); |
||
603 | answer_text = sprintf_temp; |
||
604 | need_show_text = 1; |
||
605 | break; |
||
606 | case SDL_SCANCODE_L | WITH_SHIFT: // shift-l |
||
607 | if (current_level < shift_L_allowed_until_level /* 4 */ || cheats_enabled) { |
||
608 | // if shift is not released within the delay, the cutscene is skipped |
||
609 | Uint32 delay = 250; |
||
610 | key_states[SDL_SCANCODE_LSHIFT] = 0; |
||
611 | key_states[SDL_SCANCODE_RSHIFT] = 0; |
||
612 | SDL_TimerID timer; |
||
613 | timer = SDL_AddTimer(delay, temp_shift_release_callback, NULL); |
||
614 | if (timer == 0) { |
||
615 | sdlperror("SDL_AddTimer"); |
||
616 | quit(1); |
||
617 | } |
||
618 | if (current_level == 14) { |
||
619 | next_level = 1; |
||
620 | } else { |
||
621 | if (current_level == 15 && cheats_enabled) { |
||
622 | #ifdef USE_COPYPROT |
||
623 | if (enable_copyprot) { |
||
624 | next_level = copyprot_level; |
||
625 | copyprot_level = -1; |
||
626 | } |
||
627 | #endif |
||
628 | } else { |
||
629 | next_level = current_level + 1; |
||
630 | if (!cheats_enabled && rem_min > shift_L_reduced_minutes /* 15 */) { |
||
631 | rem_min = shift_L_reduced_minutes; // 15 |
||
632 | rem_tick = shift_L_reduced_ticks; // 719 |
||
633 | } |
||
634 | } |
||
635 | } |
||
636 | stop_sounds(); |
||
637 | } |
||
638 | break; |
||
639 | #ifdef USE_QUICKSAVE |
||
640 | case SDL_SCANCODE_F6: |
||
641 | case SDL_SCANCODE_F6 | WITH_SHIFT: |
||
642 | if (Kid.alive < 0) need_quick_save = 1; |
||
643 | break; |
||
644 | case SDL_SCANCODE_F9: |
||
645 | case SDL_SCANCODE_F9 | WITH_SHIFT: |
||
646 | need_quick_load = 1; |
||
647 | break; |
||
648 | #ifdef USE_REPLAY |
||
649 | case SDL_SCANCODE_TAB | WITH_CTRL: |
||
650 | case SDL_SCANCODE_TAB | WITH_CTRL | WITH_SHIFT: |
||
651 | if (recording) { // finished recording |
||
652 | stop_recording(); |
||
653 | } |
||
654 | else { // should start recording |
||
655 | start_recording(); |
||
656 | } |
||
657 | break; |
||
658 | #endif // USE_REPLAY |
||
659 | #endif // USE_QUICKSAVE |
||
660 | } |
||
661 | if (cheats_enabled) { |
||
662 | switch (key) { |
||
663 | case SDL_SCANCODE_C: // c |
||
664 | snprintf(sprintf_temp, sizeof(sprintf_temp), "S%d L%d R%d A%d B%d", drawn_room, room_L, room_R, room_A, room_B); |
||
665 | answer_text = /*&*/sprintf_temp; |
||
666 | need_show_text = 1; |
||
667 | break; |
||
668 | case SDL_SCANCODE_C | WITH_SHIFT: // shift-c |
||
669 | snprintf(sprintf_temp, sizeof(sprintf_temp), "AL%d AR%d BL%d BR%d", room_AL, room_AR, room_BL, room_BR); |
||
670 | answer_text = /*&*/sprintf_temp; |
||
671 | need_show_text = 1; |
||
672 | break; |
||
673 | case SDL_SCANCODE_MINUS: |
||
674 | case SDL_SCANCODE_KP_MINUS: // '-' --> subtract time cheat |
||
675 | if (rem_min > 1) --rem_min; |
||
676 | |||
677 | #ifdef ALLOW_INFINITE_TIME |
||
678 | else if (rem_min < -1) ++rem_min; // if negative/infinite, time runs 'forward' |
||
679 | else if (rem_min == -1) rem_tick = 720; // resets the timer to 00:00:00 |
||
680 | #endif |
||
681 | |||
682 | text_time_total = 0; |
||
683 | text_time_remaining = 0; |
||
684 | is_show_time = 1; |
||
685 | break; |
||
686 | case SDL_SCANCODE_EQUALS | WITH_SHIFT: // '+' |
||
687 | case SDL_SCANCODE_KP_PLUS: // '+' --> add time cheat |
||
688 | |||
689 | #ifdef ALLOW_INFINITE_TIME |
||
690 | if (rem_min < 0) { // if negative/infinite, time runs 'forward' |
||
691 | if (rem_min > INT16_MIN) --rem_min; |
||
692 | } |
||
693 | else ++rem_min; |
||
694 | #else |
||
695 | ++rem_min; |
||
696 | #endif |
||
697 | |||
698 | text_time_total = 0; |
||
699 | text_time_remaining = 0; |
||
700 | is_show_time = 1; |
||
701 | break; |
||
702 | case SDL_SCANCODE_R: // R --> revive kid cheat |
||
703 | if (Kid.alive > 0) { |
||
704 | resurrect_time = 20; |
||
705 | Kid.alive = -1; |
||
706 | erase_bottom_text(1); |
||
707 | } |
||
708 | break; |
||
709 | case SDL_SCANCODE_K: // K --> kill guard cheat |
||
710 | guardhp_delta = -guardhp_curr; |
||
711 | Guard.alive = 0; |
||
712 | break; |
||
713 | case SDL_SCANCODE_I | WITH_SHIFT: // shift+I --> invert cheat |
||
714 | toggle_upside(); |
||
715 | break; |
||
716 | case SDL_SCANCODE_W | WITH_SHIFT: // shift+W --> feather fall cheat |
||
717 | feather_fall(); |
||
718 | break; |
||
719 | case SDL_SCANCODE_H: // H --> view room to the left |
||
720 | draw_guard_hp(0, 10); |
||
721 | next_room = room_L; |
||
722 | break; |
||
723 | case SDL_SCANCODE_J: // J --> view room to the right |
||
724 | draw_guard_hp(0, 10); |
||
725 | next_room = room_R; |
||
726 | break; |
||
727 | case SDL_SCANCODE_U: // U --> view room above |
||
728 | draw_guard_hp(0, 10); |
||
729 | next_room = room_A; |
||
730 | break; |
||
731 | case SDL_SCANCODE_N: // N --> view room below |
||
732 | draw_guard_hp(0, 10); |
||
733 | next_room = room_B; |
||
734 | break; |
||
735 | case SDL_SCANCODE_B | WITH_SHIFT: // shift-b |
||
736 | is_blind_mode = !is_blind_mode; |
||
737 | if (is_blind_mode) { |
||
738 | draw_rect(&rect_top, 0); |
||
739 | } else { |
||
740 | need_full_redraw = 1; |
||
741 | } |
||
742 | break; |
||
743 | case SDL_SCANCODE_S | WITH_SHIFT: // shift-s |
||
744 | if (hitp_curr != hitp_max) { |
||
745 | play_sound(sound_33_small_potion); // small potion (cheat) |
||
746 | hitp_delta = 1; |
||
747 | flash_color = 4; // red |
||
748 | flash_time = 2; |
||
749 | } |
||
750 | break; |
||
751 | case SDL_SCANCODE_T | WITH_SHIFT: // shift-t |
||
752 | play_sound(sound_30_big_potion); // big potion (cheat) |
||
753 | flash_color = 4; // red |
||
754 | flash_time = 4; |
||
755 | add_life(); |
||
756 | break; |
||
757 | #ifdef USE_DEBUG_CHEATS |
||
758 | case SDL_SCANCODE_T: |
||
759 | is_timer_displayed = 1 - is_timer_displayed; // toggle |
||
760 | if (!is_timer_displayed) { |
||
761 | need_full_redraw = 1; |
||
762 | } |
||
763 | break; |
||
764 | #endif |
||
765 | } |
||
766 | } |
||
767 | |||
768 | if (need_show_text) { |
||
769 | display_text_bottom(answer_text); |
||
770 | text_time_total = 24; |
||
771 | text_time_remaining = 24; |
||
772 | } |
||
773 | return 1; |
||
774 | } |
||
775 | |||
776 | // seg000:08EB |
||
777 | void __pascal far play_frame() { |
||
778 | do_mobs(); |
||
779 | process_trobs(); |
||
780 | check_skel(); |
||
781 | check_can_guard_see_kid(); |
||
782 | // if level is restarted, return immediately |
||
783 | if (play_kid_frame()) return; |
||
784 | play_guard_frame(); |
||
785 | if (0 == resurrect_time) { |
||
786 | check_sword_hurting(); |
||
787 | check_sword_hurt(); |
||
788 | } |
||
789 | check_sword_vs_sword(); |
||
790 | do_delta_hp(); |
||
791 | exit_room(); |
||
792 | check_the_end(); |
||
793 | check_guard_fallout(); |
||
794 | if (current_level == 0) { |
||
795 | // Special event: level 0 running exit |
||
796 | if (Kid.room == 24) { |
||
797 | draw_rect(&screen_rect, 0); |
||
798 | start_level = -1; |
||
799 | need_quotes = 1; |
||
800 | start_game(); |
||
801 | } |
||
802 | } else if(current_level == 6) { |
||
803 | // Special event: level 6 falling exit |
||
804 | if (roomleave_result == -2) { |
||
805 | Kid.y = -1; |
||
806 | stop_sounds(); |
||
807 | ++next_level; |
||
808 | } |
||
809 | } else if(current_level == 12) { |
||
810 | // Special event: level 12 running exit |
||
811 | if (Kid.room == 23) { |
||
812 | ++next_level; |
||
813 | // Sounds must be stopped, because play_level_2() checks next_level only if there are no sounds playing. |
||
814 | stop_sounds(); |
||
815 | seamless = 1; |
||
816 | } |
||
817 | } |
||
818 | show_time(); |
||
819 | // expiring doesn't count on Jaffar/princess level |
||
820 | if (current_level < 13 && rem_min == 0) { |
||
821 | expired(); |
||
822 | } |
||
823 | } |
||
824 | |||
825 | // seg000:09B6 |
||
826 | void __pascal far draw_game_frame() { |
||
827 | short var_2; |
||
828 | if (need_full_redraw) { |
||
829 | redraw_screen(0); |
||
830 | need_full_redraw = 0; |
||
831 | } else { |
||
832 | if (different_room) { |
||
833 | drawn_room = next_room; |
||
834 | if (tbl_level_type[current_level]) { |
||
835 | gen_palace_wall_colors(); |
||
836 | } |
||
837 | redraw_screen(1); |
||
838 | } else { |
||
839 | if (need_redraw_because_flipped) { |
||
840 | need_redraw_because_flipped = 0; |
||
841 | redraw_screen(0); |
||
842 | } else { |
||
843 | memset_near(&table_counts, 0, sizeof(table_counts)); |
||
844 | draw_moving(); |
||
845 | draw_tables(); |
||
846 | if (is_blind_mode) { |
||
847 | draw_rect(&rect_top, 0); |
||
848 | } |
||
849 | if (upside_down) { |
||
850 | flip_screen(offscreen_surface); |
||
851 | } |
||
852 | while (drects_count--) { |
||
853 | copy_screen_rect(&drects[drects_count]); |
||
854 | } |
||
855 | if (upside_down) { |
||
856 | flip_screen(offscreen_surface); |
||
857 | } |
||
858 | drects_count = 0; |
||
859 | } |
||
860 | } |
||
861 | } |
||
862 | |||
863 | play_next_sound(); |
||
864 | // Note: texts are identified by their total time! |
||
865 | if (text_time_remaining == 1) { |
||
866 | // If the text's is about to expire: |
||
867 | if (text_time_total == 36 || text_time_total == 288) { |
||
868 | // 36: died on demo/potions level |
||
869 | // 288: press button to continue |
||
870 | // In this case, restart the game. |
||
871 | start_level = -1; |
||
872 | need_quotes = 1; |
||
873 | |||
874 | #ifdef USE_REPLAY |
||
875 | if (recording) stop_recording(); |
||
876 | if (replaying) end_replay(); |
||
877 | #endif |
||
878 | |||
879 | start_game(); |
||
880 | } else { |
||
881 | // Otherwise, just clear it. |
||
882 | erase_bottom_text(1); |
||
883 | } |
||
884 | } else { |
||
885 | if (text_time_remaining != 0 && text_time_total != 1188) { |
||
886 | // 1188: potions level (page/line/word) -- this one does not disappear |
||
887 | --text_time_remaining; |
||
888 | if (text_time_total == 288 && text_time_remaining < 72) { |
||
889 | // 288: press button to continue |
||
890 | // Blink the message: |
||
891 | var_2 = text_time_remaining % 12; |
||
892 | if (var_2 > 3) { |
||
893 | erase_bottom_text(0); |
||
894 | } else { |
||
895 | if (var_2 == 3) { |
||
896 | display_text_bottom("Press Button to Continue"); |
||
897 | play_sound_from_buffer(sound_pointers[sound_38_blink]); // press button blink |
||
898 | } |
||
899 | } |
||
900 | } |
||
901 | } |
||
902 | } |
||
903 | } |
||
904 | |||
905 | // seg000:0B12 |
||
906 | void __pascal far anim_tile_modif() { |
||
907 | word tilepos; |
||
908 | for (tilepos = 0; tilepos < 30; ++tilepos) { |
||
909 | switch (get_curr_tile(tilepos)) { |
||
910 | case tiles_10_potion: |
||
911 | start_anim_potion(drawn_room, tilepos); |
||
912 | break; |
||
913 | case tiles_19_torch: |
||
914 | case tiles_30_torch_with_debris: |
||
915 | start_anim_torch(drawn_room, tilepos); |
||
916 | break; |
||
917 | case tiles_22_sword: |
||
918 | start_anim_sword(drawn_room, tilepos); |
||
919 | break; |
||
920 | } |
||
921 | } |
||
922 | } |
||
923 | |||
924 | // seg000:0B72 |
||
925 | void __pascal far load_sounds(int first,int last) { |
||
926 | dat_type* ibm_dat = NULL; |
||
927 | dat_type* digi1_dat = NULL; |
||
928 | // dat_type* digi2_dat = NULL; |
||
929 | dat_type* digi3_dat = NULL; |
||
930 | dat_type* midi_dat = NULL; |
||
931 | short current; |
||
932 | ibm_dat = open_dat("IBM_SND1.DAT", 0); |
||
933 | if (sound_flags & sfDigi) { |
||
934 | digi1_dat = open_dat("DIGISND1.DAT", 0); |
||
935 | // digi2_dat = open_dat("DIGISND2.DAT", 0); |
||
936 | digi3_dat = open_dat("DIGISND3.DAT", 0); |
||
937 | } |
||
938 | if (sound_flags & sfMidi) { |
||
939 | midi_dat = open_dat("MIDISND1.DAT", 0); |
||
940 | } |
||
941 | |||
942 | #ifdef USE_MIXER |
||
943 | load_sound_names(); |
||
944 | #endif |
||
945 | |||
946 | for (current = first; current <= last; ++current) { |
||
947 | if (sound_pointers[current] != NULL) continue; |
||
948 | /*if (demo_mode) { |
||
949 | sound_pointers[current] = decompress_sound((sound_buffer_type*) load_from_opendats_alloc(current + 10000)); |
||
950 | } else*/ { |
||
951 | //sound_pointers[current] = (sound_buffer_type*) load_from_opendats_alloc(current + 10000, "bin", NULL, NULL); |
||
952 | //printf("overwriting sound_pointers[%d] = %p\n", current, sound_pointers[current]); |
||
953 | |||
954 | |||
955 | sound_pointers[current] = load_sound(current); |
||
956 | } |
||
957 | } |
||
958 | if (midi_dat) close_dat(midi_dat); |
||
959 | if (digi1_dat) close_dat(digi1_dat); |
||
960 | // if (digi2_dat) close_dat(digi2_dat); |
||
961 | if (digi3_dat) close_dat(digi3_dat); |
||
962 | close_dat(ibm_dat); |
||
963 | } |
||
964 | |||
965 | // seg000:0C5E |
||
966 | void __pascal far load_opt_sounds(int first,int last) { |
||
967 | // stub |
||
968 | dat_type* ibm_dat = NULL; |
||
969 | dat_type* digi_dat = NULL; |
||
970 | dat_type* midi_dat = NULL; |
||
971 | short current; |
||
972 | ibm_dat = open_dat("IBM_SND2.DAT", 0); |
||
973 | if (sound_flags & sfDigi) { |
||
974 | digi_dat = open_dat("DIGISND2.DAT", 0); |
||
975 | } |
||
976 | if (sound_flags & sfMidi) { |
||
977 | midi_dat = open_dat("MIDISND2.DAT", 0); |
||
978 | } |
||
979 | for (current = first; current <= last; ++current) { |
||
980 | //We don't free sounds, so load only once. |
||
981 | if (sound_pointers[current] != NULL) continue; |
||
982 | /*if (demo_mode) { |
||
983 | sound_pointers[current] = decompress_sound((sound_buffer_type*) load_from_opendats_alloc(current + 10000)); |
||
984 | } else*/ { |
||
985 | //sound_pointers[current] = (sound_buffer_type*) load_from_opendats_alloc(current + 10000, "bin", NULL, NULL); |
||
986 | //printf("overwriting sound_pointers[%d] = %p\n", current, sound_pointers[current]); |
||
987 | sound_pointers[current] = load_sound(current); |
||
988 | } |
||
989 | } |
||
990 | if (midi_dat) close_dat(midi_dat); |
||
991 | if (digi_dat) close_dat(digi_dat); |
||
992 | close_dat(ibm_dat); |
||
993 | } |
||
994 | |||
995 | // data:03BA |
||
996 | const char*const tbl_guard_dat[] = {"GUARD.DAT", "FAT.DAT", "SKEL.DAT", "VIZIER.DAT", "SHADOW.DAT"}; |
||
997 | // data:03C4 |
||
998 | const char*const tbl_envir_gr[] = {"", "C", "C", "E", "E", "V"}; |
||
999 | // data:03D0 |
||
1000 | const char*const tbl_envir_ki[] = {"DUNGEON", "PALACE"}; |
||
1001 | // seg000:0D20 |
||
1002 | void __pascal far load_lev_spr(int level) { |
||
1003 | dat_type* dathandle; |
||
1004 | short guardtype; |
||
1005 | char filename[20]; |
||
1006 | dathandle = NULL; |
||
1007 | current_level = next_level = level; |
||
1008 | draw_rect(&screen_rect, 0); |
||
1009 | free_optsnd_chtab(); |
||
1010 | snprintf(filename, sizeof(filename), "%s%s.DAT", |
||
1011 | tbl_envir_gr[graphics_mode], |
||
1012 | tbl_envir_ki[tbl_level_type[current_level]] |
||
1013 | ); |
||
1014 | load_chtab_from_file(id_chtab_6_environment, 200, filename, 1<<5); |
||
1015 | load_more_opt_graf(filename); |
||
1016 | guardtype = tbl_guard_type[current_level]; |
||
1017 | if (guardtype != -1) { |
||
1018 | if (guardtype == 0) { |
||
1019 | dathandle = open_dat(tbl_level_type[current_level] ? "GUARD1.DAT" : "GUARD2.DAT", 0); |
||
1020 | } |
||
1021 | load_chtab_from_file(id_chtab_5_guard, 750, tbl_guard_dat[guardtype], 1<<8); |
||
1022 | if (dathandle) { |
||
1023 | close_dat(dathandle); |
||
1024 | } |
||
1025 | } |
||
1026 | curr_guard_color = 0; |
||
1027 | load_chtab_from_file(id_chtab_7_environmentwall, 360, filename, 1<<6); |
||
1028 | |||
1029 | // Level colors (1.3) |
||
1030 | if (graphics_mode == gmMcgaVga && level_var_palettes != NULL) { |
||
1031 | int level_color = tbl_level_color[current_level]; |
||
1032 | if (level_color != 0) { |
||
1033 | byte* env_pal = level_var_palettes + 0x30*(level_color-1); |
||
1034 | byte* wall_pal = env_pal + 0x30 * tbl_level_type[current_level]; |
||
1035 | set_pal_arr(0x50, 0x10, (rgb_type*)env_pal, 1); |
||
1036 | set_pal_arr(0x60, 0x10, (rgb_type*)wall_pal, 1); |
||
1037 | set_chtab_palette(chtab_addrs[id_chtab_6_environment], env_pal, 0x10); |
||
1038 | set_chtab_palette(chtab_addrs[id_chtab_7_environmentwall], wall_pal, 0x10); |
||
1039 | } |
||
1040 | } |
||
1041 | |||
1042 | /*if (comp_skeleton[current_level])*/ { |
||
1043 | load_opt_sounds(44, 44); // skel alive |
||
1044 | } |
||
1045 | /*if (comp_mirror[current_level])*/ { |
||
1046 | load_opt_sounds(45, 45); // mirror |
||
1047 | } |
||
1048 | /*if (comp_chomper[current_level])*/ { |
||
1049 | load_opt_sounds(46, 47); // something chopped, chomper |
||
1050 | } |
||
1051 | /*if (comp_spike[current_level])*/ { |
||
1052 | load_opt_sounds(48, 49); // something spiked, spikes |
||
1053 | } |
||
1054 | } |
||
1055 | |||
1056 | // seg000:0E6C |
||
1057 | void __pascal far load_level() { |
||
1058 | dat_type* dathandle; |
||
1059 | dathandle = open_dat("LEVELS.DAT", 0); |
||
1060 | load_from_opendats_to_area(current_level + 2000, &level, sizeof(level), "bin"); |
||
1061 | close_dat(dathandle); |
||
1062 | |||
1063 | alter_mods_allrm(); |
||
1064 | reset_level_unused_fields(true); // added |
||
1065 | } |
||
1066 | |||
1067 | void reset_level_unused_fields(bool loading_clean_level) { |
||
1068 | // Entirely unused fields in the level format: reset to zero for now |
||
1069 | // They can be repurposed to add new stuff to the level format in the future |
||
1070 | memset(level.roomxs, 0, sizeof(level.roomxs)); |
||
1071 | memset(level.roomys, 0, sizeof(level.roomys)); |
||
1072 | memset(level.fill_1, 0, sizeof(level.fill_1)); |
||
1073 | memset(level.fill_2, 0, sizeof(level.fill_2)); |
||
1074 | memset(level.fill_3, 0, sizeof(level.fill_3)); |
||
1075 | |||
1076 | // For these fields, only use the bits that are actually used, and set the rest to zero. |
||
1077 | // Good for repurposing the unused bits in the future. |
||
1078 | int i; |
||
1079 | for (i = 0; i < level.used_rooms; ++i) { |
||
1080 | //level.guards_dir[i] &= 0x01; // 1 bit in use |
||
1081 | level.guards_skill[i] &= 0x0F; // 4 bits in use |
||
1082 | } |
||
1083 | |||
1084 | // In savestates, additional information may be stored (e.g. remembered guard hp) - should not reset this then! |
||
1085 | if (loading_clean_level) { |
||
1086 | for (i = 0; i < level.used_rooms; ++i) { |
||
1087 | level.guards_color[i] &= 0x0F; // 4 bits in use (other 4 bits repurposed as remembered guard hp) |
||
1088 | } |
||
1089 | } |
||
1090 | |||
1091 | } |
||
1092 | |||
1093 | // seg000:0EA8 |
||
1094 | // returns 1 if level is restarted, 0 otherwise |
||
1095 | int __pascal far play_kid_frame() { |
||
1096 | loadkid_and_opp(); |
||
1097 | load_fram_det_col(); |
||
1098 | check_killed_shadow(); |
||
1099 | play_kid(); |
||
1100 | if (upside_down && Char.alive >= 0) { |
||
1101 | upside_down = 0; |
||
1102 | need_redraw_because_flipped = 1; |
||
1103 | } |
||
1104 | if (is_restart_level) { |
||
1105 | return 1; |
||
1106 | } |
||
1107 | if (Char.room != 0) { |
||
1108 | play_seq(); |
||
1109 | fall_accel(); |
||
1110 | fall_speed(); |
||
1111 | load_frame_to_obj(); |
||
1112 | load_fram_det_col(); |
||
1113 | set_char_collision(); |
||
1114 | bump_into_opponent(); |
||
1115 | check_collisions(); |
||
1116 | check_bumped(); |
||
1117 | check_gate_push(); |
||
1118 | check_action(); |
||
1119 | check_press(); |
||
1120 | check_spike_below(); |
||
1121 | if (resurrect_time == 0) { |
||
1122 | check_spiked(); |
||
1123 | check_chomped_kid(); |
||
1124 | } |
||
1125 | check_knock(); |
||
1126 | } |
||
1127 | savekid(); |
||
1128 | return 0; |
||
1129 | } |
||
1130 | |||
1131 | // seg000:0F48 |
||
1132 | void __pascal far play_guard_frame() { |
||
1133 | if (Guard.direction != dir_56_none) { |
||
1134 | loadshad_and_opp(); |
||
1135 | load_fram_det_col(); |
||
1136 | check_killed_shadow(); |
||
1137 | play_guard(); |
||
1138 | if (Char.room == drawn_room) { |
||
1139 | play_seq(); |
||
1140 | if (Char.x >= 44 && Char.x < 211) { |
||
1141 | fall_accel(); |
||
1142 | fall_speed(); |
||
1143 | load_frame_to_obj(); |
||
1144 | load_fram_det_col(); |
||
1145 | set_char_collision(); |
||
1146 | check_guard_bumped(); |
||
1147 | check_action(); |
||
1148 | check_press(); |
||
1149 | check_spike_below(); |
||
1150 | check_spiked(); |
||
1151 | check_chomped_guard(); |
||
1152 | } |
||
1153 | } |
||
1154 | saveshad(); |
||
1155 | } |
||
1156 | } |
||
1157 | |||
1158 | // seg000:0FBD |
||
1159 | void __pascal far check_the_end() { |
||
1160 | if (next_room != 0 && next_room != drawn_room) { |
||
1161 | drawn_room = next_room; |
||
1162 | load_room_links(); |
||
1163 | if (current_level == 14 && drawn_room == 5) { |
||
1164 | #ifdef USE_REPLAY |
||
1165 | if (recording) stop_recording(); |
||
1166 | if (replaying) end_replay(); |
||
1167 | #endif |
||
1168 | // Special event: end of game |
||
1169 | end_sequence(); |
||
1170 | } |
||
1171 | different_room = 1; |
||
1172 | loadkid(); |
||
1173 | anim_tile_modif(); |
||
1174 | start_chompers(); |
||
1175 | check_fall_flo(); |
||
1176 | check_shadow(); |
||
1177 | } |
||
1178 | } |
||
1179 | |||
1180 | // seg000:1009 |
||
1181 | void __pascal far check_fall_flo() { |
||
1182 | // Special event: falling floors |
||
1183 | if (current_level == 13 && (drawn_room == 23 || drawn_room == 16)) { |
||
1184 | get_room_address(curr_room = room_A); |
||
1185 | for (curr_tilepos = 22; curr_tilepos <= 27; ++curr_tilepos) { |
||
1186 | make_loose_fall(-(prandom(0xFF) & 0x0F)); |
||
1187 | } |
||
1188 | } |
||
1189 | } |
||
1190 | |||
1191 | void get_joystick_state(int raw_x, int raw_y, int axis_state[2]) { |
||
1192 | |||
1193 | #define DEGREES_TO_RADIANS (M_PI/180.0) |
||
1194 | |||
1195 | // check if the X/Y position is within the 'dead zone' of the joystick |
||
1196 | int dist_squared = raw_x*raw_x + raw_y*raw_y; |
||
1197 | if (dist_squared < joystick_threshold*joystick_threshold) { |
||
1198 | axis_state[0] = 0; |
||
1199 | axis_state[1] = 0; |
||
1200 | } else { |
||
1201 | double angle = atan2(raw_y, raw_x); // angle of the joystick: 0 = right, >0 = downward, <0 = upward |
||
1202 | //printf("Joystick angle is %f degrees\n", angle/DEGREES_TO_RADIANS); |
||
1203 | |||
1204 | if (fabs(angle) < (60*DEGREES_TO_RADIANS)) // 120 degree range facing right |
||
1205 | axis_state[0] = 1; |
||
1206 | |||
1207 | else if (fabs(angle) > (120*DEGREES_TO_RADIANS)) // 120 degree range facing left |
||
1208 | axis_state[0] = -1; |
||
1209 | |||
1210 | else { |
||
1211 | // joystick is neutral horizontally, so the control should be released |
||
1212 | // however: prevent stop running if the Kid was already running / trying to do a running-jump |
||
1213 | // (this tweak makes it a bit easier to do (multiple) running jumps) |
||
1214 | if (!(angle < 0 /*facing upward*/ && Kid.action == actions_1_run_jump)) { |
||
1215 | axis_state[0] = 0; |
||
1216 | } |
||
1217 | } |
||
1218 | |||
1219 | if (angle < (-30*DEGREES_TO_RADIANS) && angle > (-150*DEGREES_TO_RADIANS)) // 120 degree range facing up |
||
1220 | axis_state[1] = -1; |
||
1221 | |||
1222 | // down slightly less sensitive than up (prevent annoyance when your thumb slips down a bit by accident) |
||
1223 | // (not sure if this adjustment is really necessary) |
||
1224 | else if (angle > (35*DEGREES_TO_RADIANS) && angle < (145*DEGREES_TO_RADIANS)) // 110 degree range facing down |
||
1225 | axis_state[1] = 1; |
||
1226 | |||
1227 | else { |
||
1228 | // joystick is neutral vertically, so the control should be released |
||
1229 | // however: should prevent unintended standing up when attempting to crouch-hop |
||
1230 | if (!((Kid.frame >= frame_108_fall_land_2 && Kid.frame <= frame_112_stand_up_from_crouch_3) |
||
1231 | && angle > 0 /*facing downward*/)) |
||
1232 | { |
||
1233 | axis_state[1] = 0; |
||
1234 | } |
||
1235 | } |
||
1236 | } |
||
1237 | } |
||
1238 | |||
1239 | void get_joystick_state_hor_only(int raw_x, int axis_state[2]) { |
||
1240 | if (raw_x > joystick_threshold) { |
||
1241 | axis_state[0] = 1; |
||
1242 | } else if (raw_x < -joystick_threshold) { |
||
1243 | axis_state[0] = -1; |
||
1244 | } else axis_state[0] = 0; |
||
1245 | |||
1246 | // disregard all vertical input from the joystick controls (only use Y and A buttons or D-pad for up/down) |
||
1247 | axis_state[1] = 0; |
||
1248 | } |
||
1249 | |||
1250 | // seg000:1051 |
||
1251 | void __pascal far read_joyst_control() { |
||
1252 | |||
1253 | if (joystick_only_horizontal) { |
||
1254 | get_joystick_state_hor_only(joy_axis[SDL_CONTROLLER_AXIS_LEFTX], joy_left_stick_states); |
||
1255 | get_joystick_state_hor_only(joy_axis[SDL_CONTROLLER_AXIS_RIGHTX], joy_right_stick_states); |
||
1256 | } else { |
||
1257 | get_joystick_state(joy_axis[SDL_CONTROLLER_AXIS_LEFTX], joy_axis[SDL_CONTROLLER_AXIS_LEFTY], joy_left_stick_states); |
||
1258 | get_joystick_state(joy_axis[SDL_CONTROLLER_AXIS_RIGHTX], joy_axis[SDL_CONTROLLER_AXIS_RIGHTY], joy_right_stick_states); |
||
1259 | } |
||
1260 | |||
1261 | if (joy_left_stick_states[0] == -1 || joy_right_stick_states[0] == -1 || joy_hat_states[0] == -1) |
||
1262 | control_x = -1; |
||
1263 | |||
1264 | if (joy_left_stick_states[0] == 1 || joy_right_stick_states[0] == 1 || joy_hat_states[0] == 1) |
||
1265 | control_x = 1; |
||
1266 | |||
1267 | if (joy_left_stick_states[1] == -1 || joy_right_stick_states[1] == -1 || joy_hat_states[1] == -1 || joy_AY_buttons_state == -1) |
||
1268 | control_y = -1; |
||
1269 | |||
1270 | if (joy_left_stick_states[1] == 1 || joy_right_stick_states[1] == 1 || joy_hat_states[1] == 1 || joy_AY_buttons_state == 1) |
||
1271 | control_y = 1; |
||
1272 | |||
1273 | if (joy_X_button_state == 1 || |
||
1274 | joy_axis[SDL_CONTROLLER_AXIS_TRIGGERLEFT] > 8000 || |
||
1275 | joy_axis[SDL_CONTROLLER_AXIS_TRIGGERRIGHT] > 8000) |
||
1276 | { |
||
1277 | control_shift = -1; |
||
1278 | } |
||
1279 | |||
1280 | } |
||
1281 | |||
1282 | // seg000:10EA |
||
1283 | void __pascal far draw_kid_hp(short curr_hp,short max_hp) { |
||
1284 | short drawn_hp_index; |
||
1285 | for (drawn_hp_index = curr_hp; drawn_hp_index < max_hp; ++drawn_hp_index) { |
||
1286 | // empty HP |
||
1287 | method_6_blit_img_to_scr(get_image(id_chtab_2_kid, 217), drawn_hp_index * 7, 194, blitters_0_no_transp); |
||
1288 | } |
||
1289 | for (drawn_hp_index = 0; drawn_hp_index < curr_hp; ++drawn_hp_index) { |
||
1290 | // full HP |
||
1291 | method_6_blit_img_to_scr(get_image(id_chtab_2_kid, 216), drawn_hp_index * 7, 194, blitters_0_no_transp); |
||
1292 | } |
||
1293 | } |
||
1294 | |||
1295 | // seg000:1159 |
||
1296 | void __pascal far draw_guard_hp(short curr_hp,short max_hp) { |
||
1297 | short drawn_hp_index; |
||
1298 | short guard_charid; |
||
1299 | if (chtab_addrs[id_chtab_5_guard] == NULL) return; |
||
1300 | guard_charid = Guard.charid; |
||
1301 | if (guard_charid != charid_4_skeleton && |
||
1302 | guard_charid != charid_24_mouse && |
||
1303 | // shadow has HP only on level 12 |
||
1304 | (guard_charid != charid_1_shadow || current_level == 12) |
||
1305 | ) { |
||
1306 | for (drawn_hp_index = curr_hp; drawn_hp_index < max_hp; ++drawn_hp_index) { |
||
1307 | method_6_blit_img_to_scr(chtab_addrs[id_chtab_5_guard]->images[0], 314 - drawn_hp_index * 7, 194, blitters_9_black); |
||
1308 | } |
||
1309 | for (drawn_hp_index = 0; drawn_hp_index < curr_hp; ++drawn_hp_index) { |
||
1310 | method_6_blit_img_to_scr(chtab_addrs[id_chtab_5_guard]->images[0], 314 - drawn_hp_index * 7, 194, blitters_0_no_transp); |
||
1311 | } |
||
1312 | } |
||
1313 | } |
||
1314 | |||
1315 | // seg000:11EC |
||
1316 | void __pascal far add_life() { |
||
1317 | short hpmax = hitp_max; |
||
1318 | ++hpmax; |
||
1319 | // CusPop: set maximum number of hitpoints (max_hitp_allowed, default = 10) |
||
1320 | // if (hpmax > 10) hpmax = 10; // original |
||
1321 | if (hpmax > max_hitp_allowed) hpmax = max_hitp_allowed; |
||
1322 | hitp_max = hpmax; |
||
1323 | set_health_life(); |
||
1324 | } |
||
1325 | |||
1326 | // seg000:1200 |
||
1327 | void __pascal far set_health_life() { |
||
1328 | hitp_delta = hitp_max - hitp_curr; |
||
1329 | } |
||
1330 | |||
1331 | // seg000:120B |
||
1332 | void __pascal far draw_hp() { |
||
1333 | if (hitp_delta) { |
||
1334 | draw_kid_hp(hitp_curr, hitp_max); |
||
1335 | } |
||
1336 | if (hitp_curr == 1 && current_level != 15) { |
||
1337 | // blinking hitpoint |
||
1338 | if (rem_tick & 1) { |
||
1339 | draw_kid_hp(1, 0); |
||
1340 | } else { |
||
1341 | draw_kid_hp(0, 1); |
||
1342 | } |
||
1343 | } |
||
1344 | if (guardhp_delta) { |
||
1345 | draw_guard_hp(guardhp_curr, guardhp_max); |
||
1346 | } |
||
1347 | if (guardhp_curr == 1) { |
||
1348 | if (rem_tick & 1) { |
||
1349 | draw_guard_hp(1, 0); |
||
1350 | } else { |
||
1351 | draw_guard_hp(0, 1); |
||
1352 | } |
||
1353 | } |
||
1354 | } |
||
1355 | |||
1356 | // seg000:127B |
||
1357 | void __pascal far do_delta_hp() { |
||
1358 | // level 12: if the shadow is hurt, Kid is also hurt |
||
1359 | if (Opp.charid == charid_1_shadow && |
||
1360 | current_level == 12 && |
||
1361 | guardhp_delta != 0 |
||
1362 | ) { |
||
1363 | hitp_delta = guardhp_delta; |
||
1364 | } |
||
1365 | hitp_curr = MIN(MAX(hitp_curr + hitp_delta, 0), hitp_max); |
||
1366 | guardhp_curr = MIN(MAX(guardhp_curr + guardhp_delta, 0), guardhp_max); |
||
1367 | } |
||
1368 | |||
1369 | byte sound_prio_table[] = { |
||
1370 | 0x14, 0x1E, 0x23, 0x66, 0x32, 0x37, 0x30, 0x30, 0x4B, 0x50, 0x0A, |
||
1371 | 0x12, 0x0C, 0x0B, 0x69, 0x6E, 0x73, 0x78, 0x7D, 0x82, 0x91, 0x96, |
||
1372 | 0x9B, 0xA0, 1, 1, 1, 1, 1, 0x13, 1, 1, 1, 1, 1, 1, 1, |
||
1373 | 1, 1, 0, 1, 1, 1, 1, 0x87, 0x8C, 0x0F, 0x10, 0x19, 0x16, 1, |
||
1374 | 0, 1, 1, 1, 1, 1, 0 |
||
1375 | }; |
||
1376 | byte sound_pcspeaker_exists[] = { |
||
1377 | 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, |
||
1378 | 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
||
1379 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
||
1380 | 1, 1, 1, 0 |
||
1381 | }; |
||
1382 | |||
1383 | // seg000:12C5 |
||
1384 | void __pascal far play_sound(int sound_id) { |
||
1385 | //printf("Would play sound %d\n", sound_id); |
||
1386 | if (next_sound < 0 || sound_prio_table[sound_id] <= sound_prio_table[next_sound]) { |
||
1387 | if (NULL == sound_pointers[sound_id]) return; |
||
1388 | if (sound_pcspeaker_exists[sound_id] != 0 || sound_pointers[sound_id]->type != sound_speaker) { |
||
1389 | next_sound = sound_id; |
||
1390 | } |
||
1391 | } |
||
1392 | } |
||
1393 | |||
1394 | // seg000:1304 |
||
1395 | void __pascal far play_next_sound() { |
||
1396 | if (next_sound >= 0) { |
||
1397 | if (!check_sound_playing() || |
||
1398 | (sound_interruptible[current_sound] != 0 && sound_prio_table[next_sound] <= sound_prio_table[current_sound]) |
||
1399 | ) { |
||
1400 | current_sound = next_sound; |
||
1401 | play_sound_from_buffer(sound_pointers[current_sound]); |
||
1402 | } |
||
1403 | } |
||
1404 | next_sound = -1; |
||
1405 | } |
||
1406 | |||
1407 | // seg000:1353 |
||
1408 | void __pascal far check_sword_vs_sword() { |
||
1409 | if (Kid.frame == 167 || Guard.frame == 167) { |
||
1410 | play_sound(sound_10_sword_vs_sword); // sword vs. sword |
||
1411 | } |
||
1412 | } |
||
1413 | |||
1414 | // seg000:136A |
||
1415 | void __pascal far load_chtab_from_file(int chtab_id,int resource,const char near *filename,int palette_bits) { |
||
1416 | //printf("Loading chtab %d, id %d from %s\n",chtab_id,resource,filename); |
||
1417 | dat_type* dathandle; |
||
1418 | if (chtab_addrs[chtab_id] != NULL) return; |
||
1419 | dathandle = open_dat(filename, 0); |
||
1420 | chtab_addrs[chtab_id] = load_sprites_from_file(resource, palette_bits, 1); |
||
1421 | close_dat(dathandle); |
||
1422 | } |
||
1423 | |||
1424 | // seg000:13BA |
||
1425 | void __pascal far free_all_chtabs_from(int first) { |
||
1426 | word chtab_id; |
||
1427 | free_peels(); |
||
1428 | for (chtab_id = first; chtab_id < 10; ++chtab_id) { |
||
1429 | if (chtab_addrs[chtab_id]) { |
||
1430 | free_chtab(chtab_addrs[chtab_id]); |
||
1431 | chtab_addrs[chtab_id] = NULL; |
||
1432 | } |
||
1433 | } |
||
1434 | } |
||
1435 | |||
1436 | // seg009:12EF |
||
1437 | void __pascal far load_one_optgraf(chtab_type* chtab_ptr,dat_pal_type far *pal_ptr,int base_id,int min_index,int max_index) { |
||
1438 | short index; |
||
1439 | for (index = min_index; index <= max_index; ++index) { |
||
1440 | image_type* image = load_image(base_id + index + 1, pal_ptr); |
||
1441 | if (image != NULL) chtab_ptr->images[index] = image; |
||
1442 | } |
||
1443 | } |
||
1444 | |||
1445 | byte optgraf_min[] = {0x01, 0x1E, 0x4B, 0x4E, 0x56, 0x65, 0x7F, 0x0A}; |
||
1446 | byte optgraf_max[] = {0x09, 0x1F, 0x4D, 0x53, 0x5B, 0x7B, 0x8F, 0x0D}; |
||
1447 | // seg000:13FC |
||
1448 | void __pascal far load_more_opt_graf(const char *filename) { |
||
1449 | // stub |
||
1450 | dat_type* dathandle; |
||
1451 | dat_shpl_type area; |
||
1452 | short graf_index; |
||
1453 | dathandle = NULL; |
||
1454 | for (graf_index = 0; graf_index < 8; ++graf_index) { |
||
1455 | /*if (...) */ { |
||
1456 | if (dathandle == NULL) { |
||
1457 | dathandle = open_dat(filename, 0); |
||
1458 | load_from_opendats_to_area(200, &area, sizeof(area), "pal"); |
||
1459 | area.palette.row_bits = 0x20; |
||
1460 | } |
||
1461 | load_one_optgraf(chtab_addrs[id_chtab_6_environment], &area.palette, 1200, optgraf_min[graf_index] - 1, optgraf_max[graf_index] - 1); |
||
1462 | } |
||
1463 | } |
||
1464 | if (dathandle != NULL) { |
||
1465 | close_dat(dathandle); |
||
1466 | } |
||
1467 | } |
||
1468 | |||
1469 | // seg000:148D |
||
1470 | int __pascal far do_paused() { |
||
1471 | #ifdef USE_REPLAY |
||
1472 | if (replaying && skipping_replay) return 0; |
||
1473 | #endif |
||
1474 | |||
1475 | word key; |
||
1476 | key = 0; |
||
1477 | next_room = 0; |
||
1478 | control_shift = 0; |
||
1479 | control_y = 0; |
||
1480 | control_x = 0; |
||
1481 | if (is_joyst_mode) { |
||
1482 | read_joyst_control(); |
||
1483 | } else { |
||
1484 | read_keyb_control(); |
||
1485 | } |
||
1486 | key = process_key(); |
||
1487 | if (is_paused) { |
||
1488 | is_paused = 0; |
||
1489 | display_text_bottom("GAME PAUSED"); |
||
1490 | // busy waiting? |
||
1491 | do { |
||
1492 | idle(); |
||
1493 | //request_screen_update(); |
||
1494 | } while (! process_key()); |
||
1495 | erase_bottom_text(1); |
||
1496 | } |
||
1497 | return key || control_shift; |
||
1498 | } |
||
1499 | |||
1500 | // seg000:1500 |
||
1501 | void __pascal far read_keyb_control() { |
||
1502 | |||
1503 | if (key_states[SDL_SCANCODE_UP] || key_states[SDL_SCANCODE_HOME] || key_states[SDL_SCANCODE_PAGEUP] |
||
1504 | || key_states[SDL_SCANCODE_KP_8] || key_states[SDL_SCANCODE_KP_7] || key_states[SDL_SCANCODE_KP_9] |
||
1505 | ) { |
||
1506 | control_y = -1; |
||
1507 | } else if (key_states[SDL_SCANCODE_CLEAR] || key_states[SDL_SCANCODE_DOWN] |
||
1508 | || key_states[SDL_SCANCODE_KP_5] || key_states[SDL_SCANCODE_KP_2] |
||
1509 | ) { |
||
1510 | control_y = 1; |
||
1511 | } |
||
1512 | if (key_states[SDL_SCANCODE_LEFT] || key_states[SDL_SCANCODE_HOME] |
||
1513 | || key_states[SDL_SCANCODE_KP_4] || key_states[SDL_SCANCODE_KP_7] |
||
1514 | ) { |
||
1515 | control_x = -1; |
||
1516 | } else if (key_states[SDL_SCANCODE_RIGHT] || key_states[SDL_SCANCODE_PAGEUP] |
||
1517 | || key_states[SDL_SCANCODE_KP_6] || key_states[SDL_SCANCODE_KP_9] |
||
1518 | ) { |
||
1519 | control_x = 1; |
||
1520 | } |
||
1521 | control_shift = -(key_states[SDL_SCANCODE_LSHIFT] || key_states[SDL_SCANCODE_RSHIFT]); |
||
1522 | |||
1523 | #ifdef USE_DEBUG_CHEATS |
||
1524 | if (cheats_enabled && debug_cheats_enabled) { |
||
1525 | if (key_states[SDL_SCANCODE_RIGHTBRACKET]) ++Char.x; |
||
1526 | else if (key_states[SDL_SCANCODE_LEFTBRACKET]) --Char.x; |
||
1527 | } |
||
1528 | #endif |
||
1529 | } |
||
1530 | |||
1531 | // seg000:156D |
||
1532 | void __pascal far copy_screen_rect(const rect_type far *source_rect_ptr) { |
||
1533 | const rect_type* far target_rect_ptr; |
||
1534 | rect_type target_rect; |
||
1535 | if (upside_down) { |
||
1536 | target_rect_ptr = &target_rect; |
||
1537 | /**target_rect_ptr*/target_rect = *source_rect_ptr; |
||
1538 | /*target_rect_ptr->*/target_rect.top = 192 - source_rect_ptr->bottom; |
||
1539 | /*target_rect_ptr->*/target_rect.bottom = 192 - source_rect_ptr->top; |
||
1540 | } else { |
||
1541 | target_rect_ptr = source_rect_ptr; |
||
1542 | } |
||
1543 | method_1_blit_rect(onscreen_surface_, offscreen_surface, target_rect_ptr, target_rect_ptr, 0); |
||
1544 | #ifdef USE_LIGHTING |
||
1545 | update_lighting(target_rect_ptr); |
||
1546 | #endif |
||
1547 | } |
||
1548 | |||
1549 | // seg000:15E9 |
||
1550 | void __pascal far toggle_upside() { |
||
1551 | upside_down = ~ upside_down; |
||
1552 | need_redraw_because_flipped = 1; |
||
1553 | } |
||
1554 | |||
1555 | // seg000:15F8 |
||
1556 | void __pascal far feather_fall() { |
||
1557 | is_feather_fall = 1; |
||
1558 | flash_color = 2; // green |
||
1559 | flash_time = 3; |
||
1560 | stop_sounds(); |
||
1561 | play_sound(sound_39_low_weight); // low weight |
||
1562 | } |
||
1563 | |||
1564 | // seg000:1618 |
||
1565 | int __pascal far parse_grmode() { |
||
1566 | // stub |
||
1567 | set_gr_mode(gmMcgaVga); |
||
1568 | return gmMcgaVga; |
||
1569 | } |
||
1570 | |||
1571 | // seg000:172C |
||
1572 | void __pascal far gen_palace_wall_colors() { |
||
1573 | dword old_randseed; |
||
1574 | word prev_color; |
||
1575 | short row; |
||
1576 | short subrow; |
||
1577 | word color_base; |
||
1578 | short column; |
||
1579 | word color; |
||
1580 | |||
1581 | old_randseed = random_seed; |
||
1582 | random_seed = drawn_room; |
||
1583 | prandom(1); // discard |
||
1584 | for (row = 0; row < 3; row++) { |
||
1585 | for (subrow = 0; subrow < 4; subrow++) { |
||
1586 | if (subrow % 2) { |
||
1587 | color_base = 0x61; // 0x61..0x64 in subrow 1 and 3 |
||
1588 | } else { |
||
1589 | color_base = 0x66; // 0x66..0x69 in subrow 0 and 2 |
||
1590 | } |
||
1591 | prev_color = -1; |
||
1592 | for (column = 0; column <= 10; ++column) { |
||
1593 | do { |
||
1594 | color = color_base + prandom(3); |
||
1595 | } while (color == prev_color); |
||
1596 | palace_wall_colors[44 * row + 11 * subrow + column] = color; |
||
1597 | //palace_wall_colors[row][subrow][column] = color; |
||
1598 | prev_color = color; |
||
1599 | } |
||
1600 | } |
||
1601 | } |
||
1602 | random_seed = old_randseed; |
||
1603 | } |
||
1604 | |||
1605 | // data:042E |
||
1606 | const rect_type rect_titles = {106,24,195,296}; |
||
1607 | |||
1608 | // seg000:17E6 |
||
1609 | void __pascal far show_title() { |
||
1610 | word textcolor; |
||
1611 | load_opt_sounds(sound_50_story_2_princess, sound_55_story_1_absence); // main theme, story, princess door |
||
1612 | textcolor = get_text_color(15, color_15_brightwhite, 0x800); |
||
1613 | dont_reset_time = 0; |
||
1614 | if(offscreen_surface) free_surface(offscreen_surface); // missing in original |
||
1615 | offscreen_surface = make_offscreen_buffer(&screen_rect); |
||
1616 | load_title_images(1); |
||
1617 | current_target_surface = offscreen_surface; |
||
1618 | do_wait(timer_0); |
||
1619 | |||
1620 | draw_image_2(0 /*main title image*/, chtab_title50, 0, 0, blitters_0_no_transp); |
||
1621 | fade_in_2(offscreen_surface, 0x1000); //STUB |
||
1622 | method_1_blit_rect(onscreen_surface_, offscreen_surface, &screen_rect, &screen_rect, blitters_0_no_transp); |
||
1623 | play_sound_from_buffer(sound_pointers[54]); // main theme |
||
1624 | start_timer(timer_0, 0x82); |
||
1625 | draw_image_2(1 /*Broderbund Software presents*/, chtab_title50, 96, 106, blitters_0_no_transp); |
||
1626 | do_wait(timer_0); |
||
1627 | |||
1628 | start_timer(timer_0,0xCD); |
||
1629 | method_1_blit_rect(onscreen_surface_, offscreen_surface, &rect_titles, &rect_titles, blitters_0_no_transp); |
||
1630 | draw_image_2(0 /*main title image*/, chtab_title50, 0, 0, blitters_0_no_transp); |
||
1631 | do_wait(timer_0); |
||
1632 | |||
1633 | start_timer(timer_0,0x41); |
||
1634 | method_1_blit_rect(onscreen_surface_, offscreen_surface, &rect_titles, &rect_titles, blitters_0_no_transp); |
||
1635 | draw_image_2(0 /*main title image*/, chtab_title50, 0, 0, blitters_0_no_transp); |
||
1636 | draw_image_2(2 /*a game by Jordan Mechner*/, chtab_title50, 96, 122, blitters_0_no_transp); |
||
1637 | do_wait(timer_0); |
||
1638 | |||
1639 | start_timer(timer_0,0x10E); |
||
1640 | method_1_blit_rect(onscreen_surface_, offscreen_surface, &rect_titles, &rect_titles, blitters_0_no_transp); |
||
1641 | draw_image_2(0 /*main title image*/, chtab_title50, 0, 0, blitters_0_no_transp); |
||
1642 | do_wait(timer_0); |
||
1643 | |||
1644 | start_timer(timer_0,0xEB); |
||
1645 | method_1_blit_rect(onscreen_surface_, offscreen_surface, &rect_titles, &rect_titles, blitters_0_no_transp); |
||
1646 | draw_image_2(0 /*main title image*/, chtab_title50, 0, 0, blitters_0_no_transp); |
||
1647 | draw_image_2(3 /*Prince Of Persia*/, chtab_title50, 24, 107, blitters_10h_transp); |
||
1648 | draw_image_2(4 /*Copyright 1990 Jordan Mechner*/, chtab_title50, 48, 184, blitters_0_no_transp); |
||
1649 | do_wait(timer_0); |
||
1650 | |||
1651 | method_1_blit_rect(onscreen_surface_, offscreen_surface, &rect_titles, &rect_titles, blitters_0_no_transp); |
||
1652 | draw_image_2(0 /*story frame*/, chtab_title40, 0, 0, blitters_0_no_transp); |
||
1653 | draw_image_2(1 /*In the Sultan's absence*/, chtab_title40, 24, 25, textcolor); |
||
1654 | current_target_surface = onscreen_surface_; |
||
1655 | while (check_sound_playing()) { |
||
1656 | idle(); |
||
1657 | do_paused(); |
||
1658 | } |
||
1659 | // method_1_blit_rect(onscreen_surface_, offscreen_surface, &screen_rect, &screen_rect, blitters_0_no_transp); |
||
1660 | play_sound_from_buffer(sound_pointers[sound_55_story_1_absence]); // story 1: In the absence |
||
1661 | transition_ltr(); |
||
1662 | pop_wait(timer_0, 0x258); |
||
1663 | fade_out_2(0x800); |
||
1664 | release_title_images(); |
||
1665 | |||
1666 | load_intro(0, &pv_scene, 0); |
||
1667 | |||
1668 | load_title_images(1); |
||
1669 | current_target_surface = offscreen_surface; |
||
1670 | draw_image_2(0 /*story frame*/, chtab_title40, 0, 0, blitters_0_no_transp); |
||
1671 | draw_image_2(2 /*Marry Jaffar*/, chtab_title40, 24, 25, textcolor); |
||
1672 | fade_in_2(offscreen_surface, 0x800); |
||
1673 | draw_image_2(0 /*main title image*/, chtab_title50, 0, 0, blitters_0_no_transp); |
||
1674 | draw_image_2(3 /*Prince Of Persia*/, chtab_title50, 24, 107, blitters_10h_transp); |
||
1675 | draw_image_2(4 /*Copyright 1990 Jordan Mechner*/, chtab_title50, 48, 184, blitters_0_no_transp); |
||
1676 | while (check_sound_playing()) { |
||
1677 | idle(); |
||
1678 | do_paused(); |
||
1679 | } |
||
1680 | transition_ltr(); |
||
1681 | pop_wait(timer_0, 0x78); |
||
1682 | draw_image_2(0 /*story frame*/, chtab_title40, 0, 0, blitters_0_no_transp); |
||
1683 | draw_image_2(4 /*credits*/, chtab_title40, 24, 26, textcolor); |
||
1684 | transition_ltr(); |
||
1685 | pop_wait(timer_0, 0x168); |
||
1686 | if (hof_count) { |
||
1687 | draw_image_2(0 /*story frame*/, chtab_title40, 0, 0, blitters_0_no_transp); |
||
1688 | draw_image_2(3 /*Prince Of Persia*/, chtab_title50, 24, 24, blitters_10h_transp); |
||
1689 | show_hof(); |
||
1690 | transition_ltr(); |
||
1691 | pop_wait(timer_0, 0xF0); |
||
1692 | } |
||
1693 | current_target_surface = onscreen_surface_; |
||
1694 | while (check_sound_playing()) { |
||
1695 | idle(); |
||
1696 | do_paused(); |
||
1697 | } |
||
1698 | fade_out_2(0x1800); |
||
1699 | free_surface(offscreen_surface); |
||
1700 | offscreen_surface = NULL; // added |
||
1701 | release_title_images(); |
||
1702 | init_game(0); |
||
1703 | } |
||
1704 | |||
1705 | // seg000:1BB3 |
||
1706 | void __pascal far transition_ltr() { |
||
1707 | short position; |
||
1708 | rect_type rect; |
||
1709 | rect.top = 0; |
||
1710 | rect.bottom = 200; |
||
1711 | rect.left = 0; |
||
1712 | rect.right = 2; |
||
1713 | for (position = 0; position < 320; position += 2) { |
||
1714 | method_1_blit_rect(onscreen_surface_, offscreen_surface, &rect, &rect, 0); |
||
1715 | rect.left += 2; |
||
1716 | rect.right += 2; |
||
1717 | pop_wait(timer_1, 0); |
||
1718 | } |
||
1719 | } |
||
1720 | |||
1721 | // seg000:1C0F |
||
1722 | void __pascal far release_title_images() { |
||
1723 | if (chtab_title50) { |
||
1724 | free_chtab(chtab_title50); |
||
1725 | chtab_title50 = NULL; |
||
1726 | } |
||
1727 | if (chtab_title40) { |
||
1728 | free_chtab(chtab_title40); |
||
1729 | chtab_title40 = NULL; |
||
1730 | } |
||
1731 | } |
||
1732 | |||
1733 | // seg000:1C3A |
||
1734 | void __pascal far draw_image_2(int id, chtab_type* chtab_ptr, int xpos, int ypos, int blit) { |
||
1735 | image_type* source; |
||
1736 | image_type* decoded_image; |
||
1737 | image_type* mask; |
||
1738 | mask = NULL; |
||
1739 | if (NULL == chtab_ptr) return; |
||
1740 | source = chtab_ptr->images[id]; |
||
1741 | decoded_image = source; |
||
1742 | if (blit != blitters_0_no_transp && blit != blitters_10h_transp) { |
||
1743 | method_3_blit_mono(decoded_image, xpos, ypos, blitters_0_no_transp, blit); |
||
1744 | } else if (blit == blitters_10h_transp) { |
||
1745 | if (graphics_mode == gmCga || graphics_mode == gmHgaHerc) { |
||
1746 | //... |
||
1747 | } else { |
||
1748 | mask = decoded_image; |
||
1749 | } |
||
1750 | draw_image_transp(decoded_image, mask, xpos, ypos); |
||
1751 | if (graphics_mode == gmCga || graphics_mode == gmHgaHerc) { |
||
1752 | free_far(mask); |
||
1753 | } |
||
1754 | } else { |
||
1755 | method_6_blit_img_to_scr(decoded_image, xpos, ypos, blit); |
||
1756 | } |
||
1757 | } |
||
1758 | |||
1759 | // seg000:1D2C |
||
1760 | void __pascal far load_kid_sprite() { |
||
1761 | load_chtab_from_file(id_chtab_2_kid, 400, "KID.DAT", 1<<7); |
||
1762 | } |
||
1763 | |||
1764 | const char* save_file = "PRINCE.SAV"; |
||
1765 | |||
1766 | const char* get_save_path(char* custom_path_buffer, size_t max_len) { |
||
1767 | if (!use_custom_levelset) { |
||
1768 | return save_file; |
||
1769 | } |
||
1770 | // if playing a custom levelset, try to use the mod folder |
||
1771 | snprintf(custom_path_buffer, max_len, "mods/%s/%s", levelset_name, save_file /*PRINCE.SAV*/ ); |
||
1772 | return custom_path_buffer; |
||
1773 | } |
||
1774 | |||
1775 | // seg000:1D45 |
||
1776 | void __pascal far save_game() { |
||
1777 | word success; |
||
1778 | int handle; |
||
1779 | success = 0; |
||
1780 | char custom_save_path[POP_MAX_PATH]; |
||
1781 | const char* save_path = get_save_path(custom_save_path, sizeof(custom_save_path)); |
||
1782 | // no O_TRUNC |
||
1783 | handle = open(save_path, O_WRONLY | O_CREAT | O_BINARY, 0600); |
||
1784 | if (handle == -1) goto loc_1DB8; |
||
1785 | if (write(handle, &rem_min, 2) == 2) goto loc_1DC9; |
||
1786 | loc_1D9B: |
||
1787 | close(handle); |
||
1788 | if (!success) { |
||
1789 | unlink(save_path); |
||
1790 | } |
||
1791 | loc_1DB8: |
||
1792 | if (!success) goto loc_1E18; |
||
1793 | display_text_bottom("GAME SAVED"); |
||
1794 | goto loc_1E2E; |
||
1795 | loc_1DC9: |
||
1796 | if (write(handle, &rem_tick, 2) != 2) goto loc_1D9B; |
||
1797 | if (write(handle, ¤t_level, 2) != 2) goto loc_1D9B; |
||
1798 | if (write(handle, &hitp_beg_lev, 2) != 2) goto loc_1D9B; |
||
1799 | success = 1; |
||
1800 | goto loc_1D9B; |
||
1801 | loc_1E18: |
||
1802 | display_text_bottom("UNABLE TO SAVE GAME"); |
||
1803 | //play_sound_from_buffer(&sound_cant_save); |
||
1804 | loc_1E2E: |
||
1805 | text_time_remaining = 24; |
||
1806 | } |
||
1807 | |||
1808 | // seg000:1E38 |
||
1809 | short __pascal far load_game() { |
||
1810 | int handle; |
||
1811 | word success; |
||
1812 | success = 0; |
||
1813 | char custom_save_path[POP_MAX_PATH]; |
||
1814 | const char* save_path = get_save_path(custom_save_path, sizeof(custom_save_path)); |
||
1815 | handle = open(save_path, O_RDONLY | O_BINARY); |
||
1816 | if (handle == -1) goto loc_1E99; |
||
1817 | if (read(handle, &rem_min, 2) == 2) goto loc_1E9E; |
||
1818 | loc_1E8E: |
||
1819 | close(handle); |
||
1820 | loc_1E99: |
||
1821 | return success; |
||
1822 | loc_1E9E: |
||
1823 | if (read(handle, &rem_tick, 2) != 2) goto loc_1E8E; |
||
1824 | if (read(handle, &start_level, 2) != 2) goto loc_1E8E; |
||
1825 | if (read(handle, &hitp_beg_lev, 2) != 2) goto loc_1E8E; |
||
1826 | #ifdef USE_COPYPROT |
||
1827 | if (enable_copyprot && copyprot_level > 0) { |
||
1828 | copyprot_level = start_level; |
||
1829 | } |
||
1830 | #endif |
||
1831 | success = 1; |
||
1832 | dont_reset_time = 1; |
||
1833 | goto loc_1E8E; |
||
1834 | } |
||
1835 | |||
1836 | // seg000:1F02 |
||
1837 | void __pascal far clear_screen_and_sounds() { |
||
1838 | short index; |
||
1839 | stop_sounds(); |
||
1840 | current_target_surface = rect_sthg(onscreen_surface_, &screen_rect); |
||
1841 | |||
1842 | is_cutscene = 0; |
||
1843 | peels_count = 0; |
||
1844 | // should these be freed? |
||
1845 | for (index = 2; index < 10; ++index) { |
||
1846 | if (chtab_addrs[index]) { |
||
1847 | // Original code does not free these? |
||
1848 | free_chtab(chtab_addrs[index]); |
||
1849 | chtab_addrs[index] = NULL; |
||
1850 | } |
||
1851 | } |
||
1852 | /* //Don't free sounds. |
||
1853 | for (index = 44; index < 57; ++index) { |
||
1854 | //continue; // don't release sounds? modern machines have enough memory |
||
1855 | free_sound(sound_pointers[index]); // added |
||
1856 | sound_pointers[index] = NULL; |
||
1857 | } |
||
1858 | */ |
||
1859 | current_level = -1; |
||
1860 | } |
||
1861 | |||
1862 | // seg000:1F7B |
||
1863 | void __pascal far parse_cmdline_sound() { |
||
1864 | // stub |
||
1865 | sound_flags |= sfDigi; |
||
1866 | } |
||
1867 | |||
1868 | // seg000:226D |
||
1869 | void __pascal far free_optional_sounds() { |
||
1870 | /* //Don't free sounds. |
||
1871 | int sound_id; |
||
1872 | for (sound_id = 44; sound_id < 57; ++sound_id) { |
||
1873 | free_sound(sound_pointers[sound_id]); |
||
1874 | sound_pointers[sound_id] = NULL; |
||
1875 | } |
||
1876 | */ |
||
1877 | // stub |
||
1878 | } |
||
1879 | |||
1880 | const byte tbl_snd_is_music[] = { |
||
1881 | 0,0,0,0,0,0,0,0,0,0, //9 |
||
1882 | 0,0,0,0,0,0,0,0,0,0, //19 |
||
1883 | 0,0,0,0,1,1,1,1,1,1, //29 |
||
1884 | 1,0,1,1,1,1,1,1,0,1, //39 |
||
1885 | 1,1,0,1,0,0,0,0,0,0, //49 |
||
1886 | 1,0,1,1,1,1,1 |
||
1887 | }; |
||
1888 | |||
1889 | void reload_non_music_sounds() { |
||
1890 | int i; |
||
1891 | for (i = 0; i < COUNT(tbl_snd_is_music); ++i) { |
||
1892 | if (!tbl_snd_is_music[i]) { |
||
1893 | free_sound(sound_pointers[i]); |
||
1894 | sound_pointers[i] = NULL; |
||
1895 | } |
||
1896 | } |
||
1897 | load_sounds(0, 43); |
||
1898 | load_opt_sounds(44, 56); |
||
1899 | } |
||
1900 | |||
1901 | // seg000:22BB |
||
1902 | void __pascal far free_optsnd_chtab() { |
||
1903 | free_optional_sounds(); |
||
1904 | free_all_chtabs_from(id_chtab_3_princessinstory); |
||
1905 | } |
||
1906 | |||
1907 | // seg000:22C8 |
||
1908 | void __pascal far load_title_images(int bgcolor) { |
||
1909 | dat_type* dathandle; |
||
1910 | dathandle = open_dat("TITLE.DAT", 0); |
||
1911 | chtab_title40 = load_sprites_from_file(40, 1<<11, 1); |
||
1912 | chtab_title50 = load_sprites_from_file(50, 1<<12, 1); |
||
1913 | close_dat(dathandle); |
||
1914 | if (graphics_mode == gmMcgaVga) { |
||
1915 | // background of text frame |
||
1916 | SDL_Color color; |
||
1917 | if (bgcolor) { |
||
1918 | // RGB(4,0,18h) = #100060 = dark blue |
||
1919 | set_pal((find_first_pal_row(1<<11) << 4) + 14, 0x04, 0x00, 0x18, 1); |
||
1920 | color.r = 0x10; |
||
1921 | color.g = 0x00; |
||
1922 | color.b = 0x60; |
||
1923 | color.a = 0xFF; |
||
1924 | } else { |
||
1925 | // RGB(20h,0,0) = #800000 = dark red |
||
1926 | set_pal((find_first_pal_row(1<<11) << 4) + 14, 0x20, 0x00, 0x00, 1); |
||
1927 | color.r = 0x80; |
||
1928 | color.g = 0x00; |
||
1929 | color.b = 0x00; |
||
1930 | color.a = 0xFF; |
||
1931 | } |
||
1932 | if (NULL != chtab_title40) { |
||
1933 | SDL_SetPaletteColors(chtab_title40->images[0]->format->palette, &color, 14, 1); |
||
1934 | } |
||
1935 | } else if (graphics_mode == gmEga || graphics_mode == gmTga) { |
||
1936 | // ... |
||
1937 | } |
||
1938 | } |
||
1939 | |||
1940 | #ifdef USE_COPYPROT |
||
1941 | // data:017A |
||
1942 | const word copyprot_word[] = {9, 1, 6, 4, 5, 3, 6, 3, 4, 4, 3, 2,12, 5,13, 1, 9, 2, 2, 4, 9, 4,11, 8, 5, 4, 1, 6, 2, 4, 6, 8, 4, 2, 7,11, 5, 4, 1, 2}; |
||
1943 | // data:012A |
||
1944 | const word copyprot_line[] = {2, 1, 5, 4, 3, 5, 1, 3, 7, 2, 2, 4, 6, 6, 2, 6, 3, 1, 2, 3, 2, 2, 3,10, 5, 6, 5, 6, 3, 5, 7, 2, 2, 4, 5, 7, 2, 6, 5, 5}; |
||
1945 | // data:00DA |
||
1946 | const word copyprot_page[] = {5, 3, 7, 3, 3, 4, 1, 5,12, 5,11,10, 1, 2, 8, 8, 2, 4, 6, 1, 4, 7, 3, 2, 1, 7,10, 1, 4, 3, 4, 1, 4, 1, 8, 1, 1,10, 3, 3}; |
||
1947 | #endif |
||
1948 | |||
1949 | // seg000:23F4 |
||
1950 | void __pascal far show_copyprot(int where) { |
||
1951 | #ifdef USE_COPYPROT |
||
1952 | char sprintf_temp[140]; |
||
1953 | if (current_level != 15) return; |
||
1954 | if (where) { |
||
1955 | if (text_time_remaining || is_cutscene) return; |
||
1956 | text_time_total = 1188; |
||
1957 | text_time_remaining = 1188; |
||
1958 | is_show_time = 0; |
||
1959 | snprintf(sprintf_temp, sizeof(sprintf_temp), |
||
1960 | "WORD %d LINE %d PAGE %d", |
||
1961 | copyprot_word[copyprot_idx], copyprot_line[copyprot_idx], copyprot_page[copyprot_idx]); |
||
1962 | display_text_bottom(sprintf_temp); |
||
1963 | } else { |
||
1964 | snprintf(sprintf_temp, sizeof(sprintf_temp), |
||
1965 | "Drink potion matching the first letter of Word %d on Line %d\n" |
||
1966 | "of Page %d of the manual.", |
||
1967 | copyprot_word[copyprot_idx], copyprot_line[copyprot_idx], copyprot_page[copyprot_idx]); |
||
1968 | show_dialog(sprintf_temp); |
||
1969 | } |
||
1970 | #endif |
||
1971 | } |
||
1972 | |||
1973 | // seg000:2489 |
||
1974 | void __pascal far show_loading() { |
||
1975 | show_text(&screen_rect, 0, 0, "Loading. . . ."); |
||
1976 | } |
||
1977 | |||
1978 | // data:42C4 |
||
1979 | word which_quote; |
||
1980 | |||
1981 | char const * const tbl_quotes[2] = { |
||
1982 | "\"(****/****) Incredibly realistic. . . The " |
||
1983 | "adventurer character actually looks human as he " |
||
1984 | "runs, jumps, climbs, and hangs from ledges.\"\n" |
||
1985 | "\n" |
||
1986 | " Computer Entertainer\n" |
||
1987 | "\n" |
||
1988 | "\n" |
||
1989 | "\n" |
||
1990 | "\n" |
||
1991 | "\"A tremendous achievement. . . Mechner has crafted " |
||
1992 | "the smoothest animation ever seen in a game of this " |
||
1993 | "type.\n" |
||
1994 | "\n" |
||
1995 | "\"PRINCE OF PERSIA is the STAR WARS of its field.\"\n" |
||
1996 | "\n" |
||
1997 | " Computer Gaming World", |
||
1998 | "\"An unmitigated delight. . . comes as close to " |
||
1999 | "(perfection) as any arcade game has come in a long, " |
||
2000 | "long time. . . what makes this game so wonderful (am " |
||
2001 | "I gushing?) is that the little onscreen character " |
||
2002 | "does not move like a little onscreen character -- he " |
||
2003 | "moves like a person.\"\n" |
||
2004 | "\n" |
||
2005 | " Nibble" |
||
2006 | }; |
||
2007 | |||
2008 | // seg000:249D |
||
2009 | void __pascal far show_quotes() { |
||
2010 | //start_timer(timer_0,0); |
||
2011 | //remove_timer(timer_0); |
||
2012 | if (demo_mode && need_quotes) { |
||
2013 | draw_rect(&screen_rect, 0); |
||
2014 | show_text(&screen_rect, -1, 0, tbl_quotes[which_quote]); |
||
2015 | which_quote = !which_quote; |
||
2016 | start_timer(timer_0,0x384); |
||
2017 | } |
||
2018 | need_quotes = 0; |
||
2019 | } |
||
2020 | |||
2021 | const rect_type splash_text_1_rect = {0, 0, 50, 320}; |
||
2022 | const rect_type splash_text_2_rect = {50, 0, 200, 320}; |
||
2023 | |||
2024 | const char* splash_text_1 = "SDLPoP " SDLPOP_VERSION; |
||
2025 | const char* splash_text_2 = |
||
2026 | "To quick save/load, press F6/F9 in-game.\n" |
||
2027 | "\n" |
||
2028 | #ifdef USE_REPLAY |
||
2029 | "To record replays, press Ctrl+Tab in-game.\n" |
||
2030 | "To view replays, press Tab on the title screen.\n" |
||
2031 | "\n" |
||
2032 | #endif |
||
2033 | "Edit game.ini to customize SDLPoP.\n" |
||
2034 | "Mods also work with SDLPoP.\n" |
||
2035 | "\n" |
||
2036 | "For more information, read doc/Readme.txt.\n" |
||
2037 | "Questions? Visit http://forum.princed.org\n" |
||
2038 | "\n" |
||
2039 | "Press any key to continue..."; |
||
2040 | |||
2041 | void show_splash() { |
||
2042 | if (!enable_info_screen || start_level >= 0) return; |
||
2043 | screen_updates_suspended = 0; |
||
2044 | current_target_surface = onscreen_surface_; |
||
2045 | draw_rect(&screen_rect, 0); |
||
2046 | show_text_with_color(&splash_text_1_rect, 0, 0, splash_text_1, color_15_brightwhite); |
||
2047 | show_text_with_color(&splash_text_2_rect, 0, -1, splash_text_2, color_7_lightgray); |
||
2048 | |||
2049 | int key = 0; |
||
2050 | do { |
||
2051 | idle(); |
||
2052 | key = key_test_quit(); |
||
2053 | |||
2054 | if (joy_hat_states[0] != 0 || joy_X_button_state != 0 || joy_AY_buttons_state != 0 || joy_B_button_state != 0) { |
||
2055 | joy_hat_states[0] = 0; |
||
2056 | joy_AY_buttons_state = 0; |
||
2057 | joy_X_button_state = 0; |
||
2058 | joy_B_button_state = 0; |
||
2059 | key_states[SDL_SCANCODE_LSHIFT] = 1; // close the splash screen using the gamepad |
||
2060 | } |
||
2061 | |||
2062 | } while(key == 0 && !(key_states[SDL_SCANCODE_LSHIFT] || key_states[SDL_SCANCODE_RSHIFT])); |
||
2063 | |||
2064 | if ((key & WITH_CTRL) || (enable_quicksave && key == SDL_SCANCODE_F9) || (enable_replay && key == SDL_SCANCODE_TAB)) { |
||
2065 | extern int last_key_scancode; // defined in seg009.c |
||
2066 | last_key_scancode = key; // can immediately do Ctrl+L, etc from the splash screen |
||
2067 | } |
||
2068 | key_states[SDL_SCANCODE_LSHIFT] = 0; // don't immediately start the game if shift was pressed! |
||
2069 | key_states[SDL_SCANCODE_RSHIFT] = 0; |
||
2070 | } |