- /* 
- SDLPoP, a port/conversion of the DOS game Prince of Persia. 
- Copyright (C) 2013-2018  Dávid Nagy 
-   
- This program is free software: you can redistribute it and/or modify 
- it under the terms of the GNU General Public License as published by 
- the Free Software Foundation, either version 3 of the License, or 
- (at your option) any later version. 
-   
- This program is distributed in the hope that it will be useful, 
- but WITHOUT ANY WARRANTY; without even the implied warranty of 
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
- GNU General Public License for more details. 
-   
- You should have received a copy of the GNU General Public License 
- along with this program.  If not, see <http://www.gnu.org/licenses/>. 
-   
- The authors of this program may be contacted at http://forum.princed.org 
- */ 
-   
- #include "common.h" 
- #include <setjmp.h> 
- #include <math.h> 
-   
- // data:461E 
- dat_type * dathandle; 
-   
- // data:4C08 
- word need_redraw_because_flipped; 
-   
- // seg000:0000 
- void far pop_main() { 
-         const char* temp = check_param("seed="); 
-         if (temp != NULL) { 
-                 random_seed  = atoi(- temp +5);
-                 seed_was_init = 1; 
-         } 
-   
-         // debug only: check that the sequence table deobfuscation did not mess things up 
-         #ifdef CHECK_SEQTABLE_MATCHES_ORIGINAL 
-         check_seqtable_matches_original(); 
-         #endif 
-   
-         load_global_options(); 
-   
- #ifdef USE_REPLAY 
-         if (g_argc > 1) { 
-                 char *filename = g_argv[1]; // file dragged on top of executable or double clicked 
-                 if (e != NULL && strcasecmp(e, ".P1R") == 0) { // valid replay filename passed as first arg 
-                         start_with_replay_file(filename); 
-                 } 
-         } 
-   
-         temp = check_param("validate"); 
-         if (temp != NULL) { 
-                 is_validate_mode = 1; 
-                 start_with_replay_file(temp); 
-         } 
- #endif 
-   
-         check_mod_param(); 
-         load_mod_options(); 
-   
-         // CusPop option 
-         is_blind_mode = start_in_blind_mode; 
-         // Bug: with start_in_blind_mode enabled, moving objects are not displayed until blind mode is toggled off+on?? 
-   
-         apply_seqtbl_patches(); 
-   
-         char sprintf_temp[100]; 
-         int i; 
-   
-         dathandle = open_dat("PRINCE.DAT", 0); 
-   
-         /*video_mode =*/ parse_grmode(); 
-   
-         init_timer(60); 
-         parse_cmdline_sound(); 
-   
-         set_hc_pal(); 
-   
-         current_target_surface = rect_sthg(onscreen_surface_, &screen_rect); 
-         show_loading(); 
-         set_joy_mode(); 
-         cheats_enabled = check_param("megahit") != NULL; 
- #ifdef USE_DEBUG_CHEATS 
-         debug_cheats_enabled = check_param("debug") != NULL; 
-         if (debug_cheats_enabled) cheats_enabled = 1; // param 'megahit' not necessary if 'debug' is used 
- #endif 
-         draw_mode = check_param("draw") != NULL && cheats_enabled; 
-         demo_mode = check_param("demo") != NULL; 
-   
-         init_copyprot_dialog(); 
- #ifdef USE_REPLAY 
-         init_record_replay(); 
- #endif 
-   
-         if (cheats_enabled 
-                 #ifdef USE_REPLAY 
-                 || recording 
-                 #endif 
-         ) { 
-                 for (i = 15; i >= 0; --i) { 
-                         snprintf(- sprintf_temp , sizeof(- sprintf_temp ), "%d",-  i );
 
-                         if (check_param(sprintf_temp)) { 
-                                 start_level = i; 
-                                 break; 
-                         } 
-                 } 
-         } 
- #ifdef USE_SCREENSHOT 
-         init_screenshot(); 
- #endif 
-   
-         init_game_main(); 
- } 
-   
- byte* level_var_palettes; 
-   
- // seg000:024F 
- void __pascal far init_game_main() { 
-         doorlink1_ad = /*&*/level.doorlinks1; 
-         doorlink2_ad = /*&*/level.doorlinks2; 
-         prandom(1); 
-         if (graphics_mode == gmMcgaVga) { 
-                 // Guard palettes 
-                 guard_palettes = (byte*) load_from_opendats_alloc(10, "bin", NULL, NULL); 
-                 // (blood, hurt flash) #E00030 = red 
-                 set_pal(12, 0x38, 0x00, 0x0C, 1); 
-                 // (palace wall pattern) #C09850 = light brown 
-                 set_pal( 6, 0x30, 0x26, 0x14, 0); 
-   
-                 // Level color variations (1.3) 
-                 level_var_palettes = load_from_opendats_alloc(20, "bin", NULL, NULL); 
-         } 
-         // PRINCE.DAT: sword 
-         chtab_addrs[id_chtab_0_sword] = load_sprites_from_file(700, 1<<2, 1); 
-         // PRINCE.DAT: flame, sword on floor, potion 
-         chtab_addrs[id_chtab_1_flameswordpotion] = load_sprites_from_file(150, 1<<3, 1); 
-         close_dat(dathandle); 
- #ifdef USE_LIGHTING 
-         init_lighting(); 
- #endif 
-         load_sounds(0, 43); 
-         load_opt_sounds(43, 56); //added 
-         hof_read(); 
-         show_splash(); // added 
-         show_use_fixes_and_enhancements_prompt(); // added 
-         start_game(); 
- } 
-   
-   
- // data:02C2 
- word first_start = 1; 
- // data:4C38 
- jmp_buf setjmp_buf; 
- // seg000:0358 
- void __pascal far start_game() { 
- #ifdef USE_COPYPROT 
-         word which_entry; 
-         word pos; 
-         word entry_used[40]; 
-         byte letts_used[26]; 
- #endif 
-         screen_updates_suspended = 0; 
-         // Prevent filling of stack. 
-         // start_game is called from many places to restart the game, for example: 
-         // process_key, play_frame, draw_game_frame, play_level, control_kid, end_sequence, expired 
-         if (first_start) { 
-                 first_start = 0; 
-         } else { 
-                 draw_rect(&screen_rect, 0); 
-                 show_quotes(); 
-                 clear_screen_and_sounds(); 
-         } 
-         release_title_images(); // added 
-         free_optsnd_chtab(); // added 
- #ifdef USE_COPYPROT 
-         copyprot_plac = prandom(13); 
-         memset(&- entry_used , 0, sizeof(- entry_used ));
 
-         memset(&- letts_used , 0, sizeof(- letts_used ));
 
-         for (pos = 0; pos < 14; ++pos) { 
-                 do { 
-                         if (pos == copyprot_plac) { 
-                                 which_entry = copyprot_idx = prandom(39); 
-                         } else { 
-                                 which_entry = prandom(39); 
-                         } 
-                 } while (entry_used[which_entry] || letts_used[copyprot_letter[which_entry]-'A']); 
-                 cplevel_entr[pos] = which_entry; 
-                 entry_used[which_entry] = 1; 
-                 letts_used[copyprot_letter[which_entry]-'A'] = 1; 
-         } 
- #endif 
-         if (skip_title) { // CusPop option: skip the title sequence (level loads instantly) 
-                 int level_number = (start_level >= 0) ? start_level : first_level; 
-                 init_game(level_number); 
-                 return; 
-         } 
-   
-         if (start_level < 0) { 
-                 show_title(); 
-         } else { 
-                 init_game(start_level); 
-         } 
- } 
-   
- #ifdef USE_QUICKSAVE 
- // All these functions return true on success, false otherwise. 
-   
- FILE* quick_fp; 
-   
- int process_save(void* data, size_t data_size) { 
-         return fwrite(- data ,-  data_size , 1,-  quick_fp ) == 1;
 
- } 
-   
- int process_load(void* data, size_t data_size) { 
-         return fread(- data ,-  data_size , 1,-  quick_fp ) == 1;
 
- } 
-   
- typedef int process_func_type(void* data, size_t data_size); 
-   
- int quick_process(process_func_type process_func) { 
-         int ok = 1; 
- #define process(x) ok = ok && process_func(&(x), sizeof(x)) 
-         // level 
-         process(level); 
-         process(checkpoint); 
-         process(upside_down); 
-         process(drawn_room); 
-         process(current_level); 
-         process(next_level); 
-         process(mobs_count); 
-         process(mobs); 
-         process(trobs_count); 
-         process(trobs); 
-         process(leveldoor_open); 
-         //process(exit_room_timer); 
-         // kid 
-         process(Kid); 
-         process(hitp_curr); 
-         process(hitp_max); 
-         process(hitp_beg_lev); 
-         process(grab_timer); 
-         process(holding_sword); 
-         process(united_with_shadow); 
-         process(have_sword); 
-         /*process(ctrl1_forward); 
-         process(ctrl1_backward); 
-         process(ctrl1_up); 
-         process(ctrl1_down); 
-         process(ctrl1_shift2);*/ 
-         process(kid_sword_strike); 
-         process(pickup_obj_type); 
-         process(offguard); 
-         // guard 
-         process(Guard); 
-         process(Char); 
-         process(Opp); 
-         process(guardhp_curr); 
-         process(guardhp_max); 
-         process(demo_index); 
-         process(demo_time); 
-         process(curr_guard_color); 
-         process(guard_notice_timer); 
-         process(guard_skill); 
-         process(shadow_initialized); 
-         process(guard_refrac); 
-         process(justblocked); 
-         process(droppedout); 
-         // collision 
-         process(curr_row_coll_room); 
-         process(curr_row_coll_flags); 
-         process(below_row_coll_room); 
-         process(below_row_coll_flags); 
-         process(above_row_coll_room); 
-         process(above_row_coll_flags); 
-         process(prev_collision_row); 
-         // flash 
-         process(flash_color); 
-         process(flash_time); 
-         // sounds 
-         process(need_level1_music); 
-         process(is_screaming); 
-         process(is_feather_fall); 
-         process(last_loose_sound); 
-         //process(next_sound); 
-         //process(current_sound); 
-         // random 
-         process(random_seed); 
-         // remaining time 
-         process(rem_min); 
-         process(rem_tick); 
-         // saved controls 
-         process(control_x); 
-         process(control_y); 
-         process(control_shift); 
-         process(control_forward); 
-         process(control_backward); 
-         process(control_up); 
-         process(control_down); 
-         process(control_shift2); 
-         process(ctrl1_forward); 
-         process(ctrl1_backward); 
-         process(ctrl1_up); 
-         process(ctrl1_down); 
-         process(ctrl1_shift2); 
- #undef process 
-         return ok; 
- } 
-   
- const char* quick_file = "QUICKSAVE.SAV"; 
- const char quick_version[] = "V1.16b4 "; 
- char quick_control[] = "........"; 
- #ifdef OSX 
- #include <CoreServices/CoreServices.h> 
- #endif // OSX 
-   
- const char* get_quick_path(char* custom_path_buffer, size_t max_len) { 
-         if (!use_custom_levelset) { 
- #ifdef OSX 
-                 static char path[PATH_MAX] = ""; 
-                 if (path[0] == 0) 
-                 { 
-                         FSRef ref; 
-                         FSFindFolder (kUserDomain, kApplicationSupportFolderType, kCreateFolder, &ref); 
-                         FSRefMakePath (&ref, (UInt8 *) &path, PATH_MAX); 
-                         strcat (- path , "/Prince of Persia");
 
-                         mkdir (path, 0755); 
-                         strcat (- path , "/QUICKSAVE.SAV");
 
-                 } 
-                 return (path); 
- #else // !OSX 
-                 return quick_file; 
- #endif // OSX 
-         } 
-         // if playing a custom levelset, try to use the mod folder 
-         snprintf(- custom_path_buffer ,-  max_len , "mods/%s/%s",-  levelset_name ,-  quick_file  /*QUICKSAVE.SAV*/ );
 
-         return custom_path_buffer; 
- } 
-   
- int quick_save() { 
-         int ok = 0; 
-         char custom_quick_path[POP_MAX_PATH]; 
-         const char* path = get_quick_path(custom_quick_path, sizeof(custom_quick_path)); 
-         quick_fp  = fopen(- path , "wb");
-         if (quick_fp != NULL) { 
-                 process_save((void*) quick_version, COUNT(quick_version)); 
-                 ok = quick_process(process_save); 
-                 quick_fp = NULL; 
-         } 
-         return ok; 
- } 
-   
- void restore_room_after_quick_load() { 
-         int temp1 = curr_guard_color; 
-         int temp2 = next_level; 
-         reset_level_unused_fields(false); 
-         load_lev_spr(current_level); 
-         curr_guard_color = temp1; 
-         next_level = temp2; 
-   
-         //need_full_redraw = 1; 
-         different_room = 1; 
-         next_room = drawn_room; 
-         load_room_links(); 
-         //draw_level_first(); 
-         //gen_palace_wall_colors(); 
-         is_guard_notice = 0; // prevent guard turning around immediately 
-         draw_game_frame(); // for falling 
-         //redraw_screen(1); // for room_L 
-   
-         hitp_delta = guardhp_delta = 1; // force HP redraw 
-         draw_hp(); 
-         loadkid_and_opp(); 
-         // Get rid of "press button" message if kid was dead before quickload. 
-         text_time_total = text_time_remaining = 0; 
-         //next_sound = current_sound = -1; 
-         exit_room_timer = 0; 
- } 
-   
- int quick_load() { 
-         int ok = 0; 
-         char custom_quick_path[POP_MAX_PATH]; 
-         const char* path = get_quick_path(custom_quick_path, sizeof(custom_quick_path)); 
-         quick_fp  = fopen(- path , "rb");
-         if (quick_fp != NULL) { 
-                 // check quicksave version is compatible 
-                 process_load(quick_control, COUNT(quick_control)); 
-                 if (strcmp(- quick_control ,-  quick_version ) != 0) {
 
-                         quick_fp = NULL; 
-                         return 0; 
-                 } 
-   
-                 stop_sounds(); 
-                 start_timer(timer_0, 5); // briefly display a black screen as a visual cue 
-                 draw_rect(&screen_rect, 0); 
-                 screen_updates_suspended = 0; 
-                 request_screen_update(); 
-                 screen_updates_suspended = 1; 
-                 short old_rem_min = rem_min; 
-                 word old_rem_tick = rem_tick; 
-   
-                 ok = quick_process(process_load); 
-                 quick_fp = NULL; 
-   
-                 restore_room_after_quick_load(); 
-   
-                 do_wait(timer_0); 
-                 screen_updates_suspended = 0; 
-                 request_screen_update(); 
-   
-                 #ifdef USE_QUICKLOAD_PENALTY 
-                 // Subtract one minute from the remaining time (if it is above 5 minutes) 
-                 if (enable_quicksave_penalty && 
-                         // don't apply the penalty after time has already stopped! 
-                         (current_level < 13 || (current_level == 13 && leveldoor_open < 2)) 
-                 ) { 
-                         int ticks_elapsed = 720 * (rem_min - old_rem_min) + (rem_tick - old_rem_tick); 
-                         // don't restore time at all if the elapsed time is between 0 and 1 minutes 
-                         if (ticks_elapsed > 0 && ticks_elapsed < 720) { 
-                                 rem_min = old_rem_min; 
-                                 rem_tick = old_rem_tick; 
-                         } 
-                         else { 
-                                 if (rem_min == 6) rem_tick = 719; // crop to "5 minutes" exactly, if hitting the threshold in <1 minute 
-                                 if (rem_min > 5 /*be lenient, not much time left*/ || rem_min < 0 /*time runs 'forward' if < 0*/) { 
-                                         --rem_min; 
-                                 } 
-                         } 
-   
-                 } 
-                 #endif 
-         } 
-         return ok; 
- } 
-   
- int need_quick_save = 0; 
- int need_quick_load = 0; 
-   
- void check_quick_op() { 
-         if (!enable_quicksave) return; 
-         if (need_quick_save) { 
-                 if (!is_feather_fall && quick_save()) { 
-                         display_text_bottom("GAME SAVED"); 
-                 } else { 
-                         display_text_bottom("UNABLE TO SAVE GAME"); 
-                 } 
-                 need_quick_save = 0; 
-                 text_time_total = 24; 
-                 text_time_remaining = 24; 
-         } 
-         if (need_quick_load) { 
- #ifdef USE_REPLAY 
-                 if (recording) { 
-                         stop_recording(); // quickloading would mess up the replay! 
-                 } 
- #endif 
-                 if (quick_load()) { 
-                         display_text_bottom("GAME LOADED"); 
-                 } else { 
-                         display_text_bottom("NO SAVEGAME AVAILABLE"); 
-                 } 
-                 need_quick_load = 0; 
-                 text_time_total = 24; 
-                 text_time_remaining = 24; 
-         } 
- } 
-   
-   
- #endif // USE_QUICKSAVE 
-   
- Uint32 temp_shift_release_callback(Uint32 interval, void *param) { 
-         const Uint8* state = SDL_GetKeyboardState(NULL); 
-         if (state[SDL_SCANCODE_LSHIFT]) key_states[SDL_SCANCODE_LSHIFT] = 1; 
-         if (state[SDL_SCANCODE_RSHIFT]) key_states[SDL_SCANCODE_RSHIFT] = 1; 
-         return 0; // causes the timer to be removed 
- } 
-   
- // seg000:04CD 
- int __pascal far process_key() { 
-         char sprintf_temp[80]; 
-         int key; 
-         const char* answer_text = NULL; 
-         word need_show_text; 
-         need_show_text = 0; 
-         key = key_test_quit(); 
-   
-         if (start_level < 0) { 
-                 if (key || control_shift) { 
-                         #ifdef USE_QUICKSAVE 
-                         if (key == SDL_SCANCODE_F9) need_quick_load = 1; 
-                         #endif 
-                         #ifdef USE_REPLAY 
-                         if (key == SDL_SCANCODE_TAB || need_start_replay) { 
-                                 start_replay(); 
-                         } 
-                         else if (key == (SDL_SCANCODE_TAB | WITH_CTRL)) { 
-                                 start_level = first_level; 
-                                 start_recording(); 
-                         } else 
-                         #endif 
-                         if (key == (SDL_SCANCODE_L | WITH_CTRL)) { // ctrl-L 
-                                 if (!load_game()) return 0; 
-                         } else { 
-                                 start_level = first_level; // 1 
-                         } 
-                         draw_rect(&screen_rect, 0); 
- #ifdef USE_FADE 
-                         if (is_global_fading) { 
-                                 fade_palette_buffer->proc_restore_free(fade_palette_buffer); 
-                                 is_global_fading = 0; 
-                         } 
- #endif 
-                         start_game(); 
-                 } 
-         } 
-         // If the Kid died, enter or shift will restart the level. 
-         if (rem_min != 0 && Kid.alive > 6 && (control_shift || key == SDL_SCANCODE_RETURN)) { 
-                 key = SDL_SCANCODE_A | WITH_CTRL; // ctrl-a 
-         } 
- #ifdef USE_REPLAY 
-         if (recording) key_press_while_recording(&key); 
-         else if (replaying) key_press_while_replaying(&key); 
- #endif 
-         if (key == 0) return 0; 
-         if (is_keyboard_mode) clear_kbd_buf(); 
-   
-         if (!cheats_enabled) // Pierre-Marie Baty -- allow typing 'megahit' in game to enable cheats 
-         { 
-                 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 }; 
-                 static int megahit_index = 0; 
-                 megahit_index = (key == megahit_chars[megahit_index] ? megahit_index + 1 : 0); 
-                 if (megahit_index == sizeof (megahit_chars) / sizeof (megahit_chars[0])) 
-                 { 
-                         answer_text = "CHEATS ENABLED"; 
-                         need_show_text = 1; 
-                         cheats_enabled = 1; 
-                 } 
-         } 
-   
-         switch(key) { 
-                 case SDL_SCANCODE_ESCAPE: // esc 
-                 case SDL_SCANCODE_ESCAPE | WITH_SHIFT: // allow pause while grabbing 
-                         is_paused = 1; 
-                 break; 
-                 case SDL_SCANCODE_SPACE: // space 
-                         is_show_time = 1; 
-                 break; 
-                 case SDL_SCANCODE_A | WITH_CTRL: // ctrl-a 
-                         if (current_level != 15) { 
-                                 stop_sounds(); 
-                                 is_restart_level = 1; 
-                         } 
-                 break; 
-                 case SDL_SCANCODE_G | WITH_CTRL: // ctrl-g 
-                         // CusPoP: first and last level where saving is allowed 
- //                      if (current_level > 2 && current_level < 14) { // original 
-                         if (current_level >= saving_allowed_first_level && current_level <= saving_allowed_last_level) { 
-                                 save_game(); 
-                         } 
-                 break; 
-                 case SDL_SCANCODE_J | WITH_CTRL: // ctrl-j 
-                         if ((sound_flags & sfDigi) && sound_mode == smTandy) { 
-                                 answer_text = "JOYSTICK UNAVAILABLE"; 
-                         } else { 
-                                 if (set_joy_mode()) { 
-                                         answer_text = "JOYSTICK MODE"; 
-                                 } else { 
-                                         answer_text = "JOYSTICK NOT FOUND"; 
-                                 } 
-                         } 
-                         need_show_text = 1; 
-                 break; 
-                 case SDL_SCANCODE_K | WITH_CTRL: // ctrl-k 
-                         answer_text = "KEYBOARD MODE"; 
-                         is_joyst_mode = 0; 
-                         is_keyboard_mode = 1; 
-                         need_show_text = 1; 
-                 break; 
-                 case SDL_SCANCODE_R | WITH_CTRL: // ctrl-r 
-                         start_level = -1; 
-                         start_game(); 
-                 break; 
-                 case SDL_SCANCODE_S | WITH_CTRL: // ctrl-s 
-                         turn_sound_on_off((!is_sound_on) * 15); 
-                         answer_text = "SOUND OFF"; 
-                         if (is_sound_on) { 
-                                 answer_text = "SOUND ON"; 
-                         } 
-                         // 
-                         need_show_text = 1; 
-                 break; 
-                 case SDL_SCANCODE_V | WITH_CTRL: // ctrl-v 
-                         //answer_text = "PRINCE OF PERSIA  V1.0"; 
-                         snprintf(- sprintf_temp , sizeof(- sprintf_temp ), "Prince of Persia v%s-SDL\n",-  SDLPOP_VERSION );
 
-                         answer_text = sprintf_temp; 
-                         need_show_text = 1; 
-                 break; 
-                 case SDL_SCANCODE_L | WITH_SHIFT: // shift-l 
-                         if (current_level < shift_L_allowed_until_level /* 4 */ || cheats_enabled) { 
-                                 // if shift is not released within the delay, the cutscene is skipped 
-                                 Uint32 delay = 250; 
-                                 key_states[SDL_SCANCODE_LSHIFT] = 0; 
-                                 key_states[SDL_SCANCODE_RSHIFT] = 0; 
-                                 SDL_TimerID timer; 
-                                 timer = SDL_AddTimer(delay, temp_shift_release_callback, NULL); 
-                                 if (timer == 0) { 
-                                         sdlperror("SDL_AddTimer"); 
-                                         quit(1); 
-                                 } 
-                                 if (current_level == 14) { 
-                                         next_level = 1; 
-                                 } else { 
-                                         if (current_level == 15 && cheats_enabled) { 
- #ifdef USE_COPYPROT 
-                                                 if (enable_copyprot) { 
-                                                         next_level = copyprot_level; 
-                                                         copyprot_level = -1; 
-                                                 } 
- #endif 
-                                         } else { 
-                                                 next_level = current_level + 1; 
-                                                 if (!cheats_enabled && rem_min > shift_L_reduced_minutes /* 15 */) { 
-                                                         rem_min = shift_L_reduced_minutes; // 15 
-                                                         rem_tick = shift_L_reduced_ticks; // 719 
-                                                 } 
-                                         } 
-                                 } 
-                                 stop_sounds(); 
-                         } 
-                 break; 
- #ifdef USE_QUICKSAVE 
-                 case SDL_SCANCODE_F6: 
-                 case SDL_SCANCODE_F6 | WITH_SHIFT: 
-                         if (Kid.alive < 0) need_quick_save = 1; 
-                 break; 
-                 case SDL_SCANCODE_F9: 
-                 case SDL_SCANCODE_F9 | WITH_SHIFT: 
-                         need_quick_load = 1; 
-                 break; 
- #ifdef USE_REPLAY 
-                 case SDL_SCANCODE_TAB | WITH_CTRL: 
-                 case SDL_SCANCODE_TAB | WITH_CTRL | WITH_SHIFT: 
-                         if (recording) { // finished recording 
-                                 stop_recording(); 
-                         } 
-                         else { // should start recording 
-                                 start_recording(); 
-                         } 
-                 break; 
- #endif // USE_REPLAY 
- #endif // USE_QUICKSAVE 
-         } 
-         if (cheats_enabled) { 
-                 switch (key) { 
-                         case SDL_SCANCODE_C: // c 
-                                 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 );
 
-                                 answer_text = /*&*/sprintf_temp; 
-                                 need_show_text = 1; 
-                         break; 
-                         case SDL_SCANCODE_C | WITH_SHIFT: // shift-c 
-                                 snprintf(- sprintf_temp , sizeof(- sprintf_temp ), "AL%d AR%d BL%d BR%d",-  room_AL ,-  room_AR ,-  room_BL ,-  room_BR );
 
-                                 answer_text = /*&*/sprintf_temp; 
-                                 need_show_text = 1; 
-                         break; 
-                         case SDL_SCANCODE_MINUS: 
-                         case SDL_SCANCODE_KP_MINUS:             // '-' --> subtract time cheat 
-                                 if (rem_min > 1) --rem_min; 
-   
- #ifdef ALLOW_INFINITE_TIME 
-                                 else if (rem_min < -1) ++rem_min; // if negative/infinite, time runs 'forward' 
-                                 else if (rem_min == -1) rem_tick = 720; // resets the timer to 00:00:00 
- #endif 
-   
-                                 text_time_total = 0; 
-                                 text_time_remaining = 0; 
-                                 is_show_time = 1; 
-                         break; 
-                         case SDL_SCANCODE_EQUALS | WITH_SHIFT: // '+' 
-                         case SDL_SCANCODE_KP_PLUS:         // '+' --> add time cheat 
-   
- #ifdef ALLOW_INFINITE_TIME 
-                                 if (rem_min < 0) { // if negative/infinite, time runs 'forward' 
-                                         if (rem_min > INT16_MIN) --rem_min; 
-                                 } 
-                                 else ++rem_min; 
- #else 
-                                 ++rem_min; 
- #endif 
-   
-                                 text_time_total = 0; 
-                                 text_time_remaining = 0; 
-                                 is_show_time = 1; 
-                         break; 
-                         case SDL_SCANCODE_R: // R --> revive kid cheat 
-                                 if (Kid.alive > 0) { 
-                                         resurrect_time = 20; 
-                                         Kid.alive = -1; 
-                                         erase_bottom_text(1); 
-                                 } 
-                         break; 
-                         case SDL_SCANCODE_K: // K --> kill guard cheat 
-                                 guardhp_delta = -guardhp_curr; 
-                                 Guard.alive = 0; 
-                         break; 
-                         case SDL_SCANCODE_I | WITH_SHIFT: // shift+I --> invert cheat 
-                                 toggle_upside(); 
-                         break; 
-                         case SDL_SCANCODE_W | WITH_SHIFT: // shift+W --> feather fall cheat 
-                                 feather_fall(); 
-                         break; 
-                         case SDL_SCANCODE_H: // H --> view room to the left 
-                                 draw_guard_hp(0, 10); 
-                                 next_room = room_L; 
-                         break; 
-                         case SDL_SCANCODE_J: // J --> view room to the right 
-                                 draw_guard_hp(0, 10); 
-                                 next_room = room_R; 
-                         break; 
-                         case SDL_SCANCODE_U: // U --> view room above 
-                                 draw_guard_hp(0, 10); 
-                                 next_room = room_A; 
-                         break; 
-                         case SDL_SCANCODE_N: // N --> view room below 
-                                 draw_guard_hp(0, 10); 
-                                 next_room = room_B; 
-                         break; 
-                         case SDL_SCANCODE_B | WITH_SHIFT: // shift-b 
-                                 is_blind_mode = !is_blind_mode; 
-                                 if (is_blind_mode) { 
-                                         draw_rect(&rect_top, 0); 
-                                 } else { 
-                                         need_full_redraw = 1; 
-                                 } 
-                         break; 
-                         case SDL_SCANCODE_S | WITH_SHIFT: // shift-s 
-                                 if (hitp_curr != hitp_max) { 
-                                         play_sound(sound_33_small_potion); // small potion (cheat) 
-                                         hitp_delta = 1; 
-                                         flash_color = 4; // red 
-                                         flash_time = 2; 
-                                 } 
-                         break; 
-                         case SDL_SCANCODE_T | WITH_SHIFT: // shift-t 
-                                 play_sound(sound_30_big_potion); // big potion (cheat) 
-                                 flash_color = 4; // red 
-                                 flash_time = 4; 
-                                 add_life(); 
-                         break; 
-                         #ifdef USE_DEBUG_CHEATS 
-                         case SDL_SCANCODE_T: 
-                                 is_timer_displayed = 1 - is_timer_displayed; // toggle 
-                                 if (!is_timer_displayed) { 
-                                         need_full_redraw = 1; 
-                                 } 
-                         break; 
-                         #endif 
-                 } 
-         } 
-   
-         if (need_show_text) { 
-                 display_text_bottom(answer_text); 
-                 text_time_total = 24; 
-                 text_time_remaining = 24; 
-         } 
-         return 1; 
- } 
-   
- // seg000:08EB 
- void __pascal far play_frame() { 
-         do_mobs(); 
-         process_trobs(); 
-         check_skel(); 
-         check_can_guard_see_kid(); 
-         // if level is restarted, return immediately 
-         if (play_kid_frame()) return; 
-         play_guard_frame(); 
-         if (0 == resurrect_time) { 
-                 check_sword_hurting(); 
-                 check_sword_hurt(); 
-         } 
-         check_sword_vs_sword(); 
-         do_delta_hp(); 
-         exit_room(); 
-         check_the_end(); 
-         check_guard_fallout(); 
-         if (current_level == 0) { 
-                 // Special event: level 0 running exit 
-                 if (Kid.room == 24) { 
-                         draw_rect(&screen_rect, 0); 
-                         start_level = -1; 
-                         need_quotes = 1; 
-                         start_game(); 
-                 } 
-         } else if(current_level == 6) { 
-                 // Special event: level 6 falling exit 
-                 if (roomleave_result == -2) { 
-                         Kid.y = -1; 
-                         stop_sounds(); 
-                         ++next_level; 
-                 } 
-         } else if(current_level == 12) { 
-                 // Special event: level 12 running exit 
-                 if (Kid.room == 23) { 
-                         ++next_level; 
- // Sounds must be stopped, because play_level_2() checks next_level only if there are no sounds playing. 
-                         stop_sounds(); 
-                         seamless = 1; 
-                 } 
-         } 
-         show_time(); 
-         // expiring doesn't count on Jaffar/princess level 
-         if (current_level < 13 && rem_min == 0) { 
-                 expired(); 
-         } 
- } 
-   
- // seg000:09B6 
- void __pascal far draw_game_frame() { 
-         short var_2; 
-         if (need_full_redraw) { 
-                 redraw_screen(0); 
-                 need_full_redraw = 0; 
-         } else { 
-                 if (different_room) { 
-                         drawn_room = next_room; 
-                         if (tbl_level_type[current_level]) { 
-                                 gen_palace_wall_colors(); 
-                         } 
-                         redraw_screen(1); 
-                 } else { 
-                         if (need_redraw_because_flipped) { 
-                                 need_redraw_because_flipped = 0; 
-                                 redraw_screen(0); 
-                         } else { 
-                                 memset_near(&table_counts, 0, sizeof(table_counts)); 
-                                 draw_moving(); 
-                                 draw_tables(); 
-                                 if (is_blind_mode) { 
-                                         draw_rect(&rect_top, 0); 
-                                 } 
-                                 if (upside_down) { 
-                                         flip_screen(offscreen_surface); 
-                                 } 
-                                 while (drects_count--) { 
-                                         copy_screen_rect(&drects[drects_count]); 
-                                 } 
-                                 if (upside_down) { 
-                                         flip_screen(offscreen_surface); 
-                                 } 
-                                 drects_count = 0; 
-                         } 
-                 } 
-         } 
-   
-         play_next_sound(); 
-         // Note: texts are identified by their total time! 
-         if (text_time_remaining == 1) { 
-                 // If the text's is about to expire: 
-                 if (text_time_total == 36 || text_time_total == 288) { 
-                         // 36: died on demo/potions level 
-                         // 288: press button to continue 
-                         // In this case, restart the game. 
-                         start_level = -1; 
-                         need_quotes = 1; 
-   
- #ifdef USE_REPLAY 
-                         if (recording) stop_recording(); 
-                         if (replaying) end_replay(); 
- #endif 
-   
-                         start_game(); 
-                 } else { 
-                         // Otherwise, just clear it. 
-                         erase_bottom_text(1); 
-                 } 
-         } else { 
-                 if (text_time_remaining != 0 && text_time_total != 1188) { 
-                         // 1188: potions level (page/line/word) -- this one does not disappear 
-                         --text_time_remaining; 
-                         if (text_time_total == 288 && text_time_remaining < 72) { 
-                                 // 288: press button to continue 
-                                 // Blink the message: 
-                                 var_2 = text_time_remaining % 12; 
-                                 if (var_2 > 3) { 
-                                         erase_bottom_text(0); 
-                                 } else { 
-                                         if (var_2 == 3) { 
-                                                 display_text_bottom("Press Button to Continue"); 
-                                                 play_sound_from_buffer(sound_pointers[sound_38_blink]); // press button blink 
-                                         } 
-                                 } 
-                         } 
-                 } 
-         } 
- } 
-   
- // seg000:0B12 
- void __pascal far anim_tile_modif() { 
-         word tilepos; 
-         for (tilepos = 0; tilepos < 30; ++tilepos) { 
-                 switch (get_curr_tile(tilepos)) { 
-                         case tiles_10_potion: 
-                                 start_anim_potion(drawn_room, tilepos); 
-                         break; 
-                         case tiles_19_torch: 
-                         case tiles_30_torch_with_debris: 
-                                 start_anim_torch(drawn_room, tilepos); 
-                         break; 
-                         case tiles_22_sword: 
-                                 start_anim_sword(drawn_room, tilepos); 
-                         break; 
-                 } 
-         } 
- } 
-   
- // seg000:0B72 
- void __pascal far load_sounds(int first,int last) { 
-         dat_type* ibm_dat = NULL; 
-         dat_type* digi1_dat = NULL; 
- //      dat_type* digi2_dat = NULL; 
-         dat_type* digi3_dat = NULL; 
-         dat_type* midi_dat = NULL; 
-         short current; 
-         ibm_dat = open_dat("IBM_SND1.DAT", 0); 
-         if (sound_flags & sfDigi) { 
-                 digi1_dat = open_dat("DIGISND1.DAT", 0); 
- //              digi2_dat = open_dat("DIGISND2.DAT", 0); 
-                 digi3_dat = open_dat("DIGISND3.DAT", 0); 
-         } 
-         if (sound_flags & sfMidi) { 
-                 midi_dat = open_dat("MIDISND1.DAT", 0); 
-         } 
-   
-         #ifdef USE_MIXER 
-         load_sound_names(); 
-         #endif 
-   
-         for (current = first; current <= last; ++current) { 
-                 if (sound_pointers[current] != NULL) continue; 
-                 /*if (demo_mode) { 
-                         sound_pointers[current] = decompress_sound((sound_buffer_type*) load_from_opendats_alloc(current + 10000)); 
-                 } else*/ { 
-                         //sound_pointers[current] = (sound_buffer_type*) load_from_opendats_alloc(current + 10000, "bin", NULL, NULL); 
-                         //printf("overwriting sound_pointers[%d] = %p\n", current, sound_pointers[current]); 
-   
-   
-                         sound_pointers[current] = load_sound(current); 
-                 } 
-         } 
-         if (midi_dat) close_dat(midi_dat); 
-         if (digi1_dat) close_dat(digi1_dat); 
- //      if (digi2_dat) close_dat(digi2_dat); 
-         if (digi3_dat) close_dat(digi3_dat); 
-         close_dat(ibm_dat); 
- } 
-   
- // seg000:0C5E 
- void __pascal far load_opt_sounds(int first,int last) { 
-         // stub 
-         dat_type* ibm_dat = NULL; 
-         dat_type* digi_dat = NULL; 
-         dat_type* midi_dat = NULL; 
-         short current; 
-         ibm_dat = open_dat("IBM_SND2.DAT", 0); 
-         if (sound_flags & sfDigi) { 
-                 digi_dat = open_dat("DIGISND2.DAT", 0); 
-         } 
-         if (sound_flags & sfMidi) { 
-                 midi_dat = open_dat("MIDISND2.DAT", 0); 
-         } 
-         for (current = first; current <= last; ++current) { 
-                 //We don't free sounds, so load only once. 
-                 if (sound_pointers[current] != NULL) continue; 
-                 /*if (demo_mode) { 
-                         sound_pointers[current] = decompress_sound((sound_buffer_type*) load_from_opendats_alloc(current + 10000)); 
-                 } else*/ { 
-                         //sound_pointers[current] = (sound_buffer_type*) load_from_opendats_alloc(current + 10000, "bin", NULL, NULL); 
-                         //printf("overwriting sound_pointers[%d] = %p\n", current, sound_pointers[current]); 
-                         sound_pointers[current] = load_sound(current); 
-                 } 
-         } 
-         if (midi_dat) close_dat(midi_dat); 
-         if (digi_dat) close_dat(digi_dat); 
-         close_dat(ibm_dat); 
- } 
-   
- // data:03BA 
- const char*const tbl_guard_dat[] = {"GUARD.DAT", "FAT.DAT", "SKEL.DAT", "VIZIER.DAT", "SHADOW.DAT"}; 
- // data:03C4 
- const char*const tbl_envir_gr[] = {"", "C", "C", "E", "E", "V"}; 
- // data:03D0 
- const char*const tbl_envir_ki[] = {"DUNGEON", "PALACE"}; 
- // seg000:0D20 
- void __pascal far load_lev_spr(int level) { 
-         dat_type* dathandle; 
-         short guardtype; 
-         char filename[20]; 
-         dathandle = NULL; 
-         current_level = next_level = level; 
-         draw_rect(&screen_rect, 0); 
-         free_optsnd_chtab(); 
-         snprintf(- filename , sizeof(- filename ), "%s%s.DAT",
 
-                 tbl_envir_gr[graphics_mode], 
-                 tbl_envir_ki[tbl_level_type[current_level]] 
-         ); 
-         load_chtab_from_file(id_chtab_6_environment, 200, filename, 1<<5); 
-         load_more_opt_graf(filename); 
-         guardtype = tbl_guard_type[current_level]; 
-         if (guardtype != -1) { 
-                 if (guardtype == 0) { 
-                         dathandle = open_dat(tbl_level_type[current_level] ? "GUARD1.DAT" : "GUARD2.DAT", 0); 
-                 } 
-                 load_chtab_from_file(id_chtab_5_guard, 750, tbl_guard_dat[guardtype], 1<<8); 
-                 if (dathandle) { 
-                         close_dat(dathandle); 
-                 } 
-         } 
-         curr_guard_color = 0; 
-         load_chtab_from_file(id_chtab_7_environmentwall, 360, filename, 1<<6); 
-   
-         // Level colors (1.3) 
-         if (graphics_mode == gmMcgaVga && level_var_palettes != NULL) { 
-                 int level_color = tbl_level_color[current_level]; 
-                 if (level_color != 0) { 
-                         byte* env_pal = level_var_palettes + 0x30*(level_color-1); 
-                         byte* wall_pal = env_pal + 0x30 * tbl_level_type[current_level]; 
-                         set_pal_arr(0x50, 0x10, (rgb_type*)env_pal, 1); 
-                         set_pal_arr(0x60, 0x10, (rgb_type*)wall_pal, 1); 
-                         set_chtab_palette(chtab_addrs[id_chtab_6_environment], env_pal, 0x10); 
-                         set_chtab_palette(chtab_addrs[id_chtab_7_environmentwall], wall_pal, 0x10); 
-                 } 
-         } 
-   
-         /*if (comp_skeleton[current_level])*/ { 
-                 load_opt_sounds(44, 44); // skel alive 
-         } 
-         /*if (comp_mirror[current_level])*/ { 
-                 load_opt_sounds(45, 45); // mirror 
-         } 
-         /*if (comp_chomper[current_level])*/ { 
-                 load_opt_sounds(46, 47); // something chopped, chomper 
-         } 
-         /*if (comp_spike[current_level])*/ { 
-                 load_opt_sounds(48, 49); // something spiked, spikes 
-         } 
- } 
-   
- // seg000:0E6C 
- void __pascal far load_level() { 
-         dat_type* dathandle; 
-         dathandle = open_dat("LEVELS.DAT", 0); 
-         load_from_opendats_to_area(current_level + 2000, &level, sizeof(level), "bin"); 
-         close_dat(dathandle); 
-   
-         alter_mods_allrm(); 
-         reset_level_unused_fields(true); // added 
- } 
-   
- void reset_level_unused_fields(bool loading_clean_level) { 
-         // Entirely unused fields in the level format: reset to zero for now 
-         // They can be repurposed to add new stuff to the level format in the future 
-         memset(- level. roomxs, 0, sizeof(- level. roomxs));
 
-         memset(- level. roomys, 0, sizeof(- level. roomys));
 
-         memset(- level. fill_1, 0, sizeof(- level. fill_1));
 
-         memset(- level. fill_2, 0, sizeof(- level. fill_2));
 
-         memset(- level. fill_3, 0, sizeof(- level. fill_3));
 
-   
-         // For these fields, only use the bits that are actually used, and set the rest to zero. 
-         // Good for repurposing the unused bits in the future. 
-         int i; 
-         for (i = 0; i < level.used_rooms; ++i) { 
-                 //level.guards_dir[i]   &= 0x01; // 1 bit in use 
-                 level.guards_skill[i] &= 0x0F; // 4 bits in use 
-         } 
-   
-         // In savestates, additional information may be stored (e.g. remembered guard hp) - should not reset this then! 
-         if (loading_clean_level) { 
-                 for (i = 0; i < level.used_rooms; ++i) { 
-                         level.guards_color[i] &= 0x0F; // 4 bits in use (other 4 bits repurposed as remembered guard hp) 
-                 } 
-         } 
-   
- } 
-   
- // seg000:0EA8 
- // returns 1 if level is restarted, 0 otherwise 
- int __pascal far play_kid_frame() { 
-         loadkid_and_opp(); 
-         load_fram_det_col(); 
-         check_killed_shadow(); 
-         play_kid(); 
-         if (upside_down && Char.alive >= 0) { 
-                 upside_down = 0; 
-                 need_redraw_because_flipped = 1; 
-         } 
-         if (is_restart_level) { 
-                 return 1; 
-         } 
-         if (Char.room != 0) { 
-                 play_seq(); 
-                 fall_accel(); 
-                 fall_speed(); 
-                 load_frame_to_obj(); 
-                 load_fram_det_col(); 
-                 set_char_collision(); 
-                 bump_into_opponent(); 
-                 check_collisions(); 
-                 check_bumped(); 
-                 check_gate_push(); 
-                 check_action(); 
-                 check_press(); 
-                 check_spike_below(); 
-                 if (resurrect_time == 0) { 
-                         check_spiked(); 
-                         check_chomped_kid(); 
-                 } 
-                 check_knock(); 
-         } 
-         savekid(); 
-         return 0; 
- } 
-   
- // seg000:0F48 
- void __pascal far play_guard_frame() { 
-         if (Guard.direction != dir_56_none) { 
-                 loadshad_and_opp(); 
-                 load_fram_det_col(); 
-                 check_killed_shadow(); 
-                 play_guard(); 
-                 if (Char.room == drawn_room) { 
-                         play_seq(); 
-                         if (Char.x >= 44 && Char.x < 211) { 
-                                 fall_accel(); 
-                                 fall_speed(); 
-                                 load_frame_to_obj(); 
-                                 load_fram_det_col(); 
-                                 set_char_collision(); 
-                                 check_guard_bumped(); 
-                                 check_action(); 
-                                 check_press(); 
-                                 check_spike_below(); 
-                                 check_spiked(); 
-                                 check_chomped_guard(); 
-                         } 
-                 } 
-                 saveshad(); 
-         } 
- } 
-   
- // seg000:0FBD 
- void __pascal far check_the_end() { 
-         if (next_room != 0 && next_room != drawn_room) { 
-                 drawn_room = next_room; 
-                 load_room_links(); 
-                 if (current_level == 14 && drawn_room == 5) { 
- #ifdef USE_REPLAY 
-                         if (recording) stop_recording(); 
-                         if (replaying) end_replay(); 
- #endif 
-                         // Special event: end of game 
-                         end_sequence(); 
-                 } 
-                 different_room = 1; 
-                 loadkid(); 
-                 anim_tile_modif(); 
-                 start_chompers(); 
-                 check_fall_flo(); 
-                 check_shadow(); 
-         } 
- } 
-   
- // seg000:1009 
- void __pascal far check_fall_flo() { 
-         // Special event: falling floors 
-         if (current_level == 13 && (drawn_room == 23 || drawn_room == 16)) { 
-                 get_room_address(curr_room = room_A); 
-                 for (curr_tilepos = 22; curr_tilepos <= 27; ++curr_tilepos) { 
-                         make_loose_fall(-(prandom(0xFF) & 0x0F)); 
-                 } 
-         } 
- } 
-   
- void get_joystick_state(int raw_x, int raw_y, int axis_state[2]) { 
-   
- #define DEGREES_TO_RADIANS (M_PI/180.0) 
-   
-         // check if the X/Y position is within the 'dead zone' of the joystick 
-         int dist_squared = raw_x*raw_x + raw_y*raw_y; 
-         if (dist_squared < joystick_threshold*joystick_threshold) { 
-                 axis_state[0] = 0; 
-                 axis_state[1] = 0; 
-         } else { 
-                 double-  angle  = atan2(- raw_y ,-  raw_x ); // angle of the joystick: 0 = right, >0 = downward, <0 = upward
 
-                 //printf("Joystick angle is %f degrees\n", angle/DEGREES_TO_RADIANS); 
-   
-                 if (fabs(- angle ) < (60*- DEGREES_TO_RADIANS )) // 120 degree range facing right
 
-                         axis_state[0] = 1; 
-   
-                 else if (fabs(- angle ) > (120*- DEGREES_TO_RADIANS )) // 120 degree range facing left
 
-                         axis_state[0] = -1; 
-   
-                 else { 
-                         // joystick is neutral horizontally, so the control should be released 
-                         // however: prevent stop running if the Kid was already running / trying to do a running-jump 
-                         // (this tweak makes it a bit easier to do (multiple) running jumps) 
-                         if (!(angle < 0 /*facing upward*/ && Kid.action == actions_1_run_jump)) { 
-                                 axis_state[0] = 0; 
-                         } 
-                 } 
-   
-                 if (angle < (-30*DEGREES_TO_RADIANS) && angle > (-150*DEGREES_TO_RADIANS)) // 120 degree range facing up 
-                         axis_state[1] = -1; 
-   
-                 // down slightly less sensitive than up (prevent annoyance when your thumb slips down a bit by accident) 
-                 // (not sure if this adjustment is really necessary) 
-                 else if (angle > (35*DEGREES_TO_RADIANS) && angle < (145*DEGREES_TO_RADIANS)) // 110 degree range facing down 
-                         axis_state[1] = 1; 
-   
-                 else { 
-                         // joystick is neutral vertically, so the control should be released 
-                         // however: should prevent unintended standing up when attempting to crouch-hop 
-                         if (!((Kid.frame >= frame_108_fall_land_2 && Kid.frame <= frame_112_stand_up_from_crouch_3) 
-                                   && angle > 0 /*facing downward*/)) 
-                         { 
-                                 axis_state[1] = 0; 
-                         } 
-                 } 
-         } 
- } 
-   
- void get_joystick_state_hor_only(int raw_x, int axis_state[2]) { 
-         if (raw_x > joystick_threshold) { 
-                 axis_state[0] = 1; 
-         } else if (raw_x < -joystick_threshold) { 
-                 axis_state[0] = -1; 
-         } else axis_state[0] = 0; 
-   
-         // disregard all vertical input from the joystick controls (only use Y and A buttons or D-pad for up/down) 
-         axis_state[1] = 0; 
- } 
-   
- // seg000:1051 
- void __pascal far read_joyst_control() { 
-   
-         if (joystick_only_horizontal) { 
-                 get_joystick_state_hor_only(joy_axis[SDL_CONTROLLER_AXIS_LEFTX], joy_left_stick_states); 
-                 get_joystick_state_hor_only(joy_axis[SDL_CONTROLLER_AXIS_RIGHTX], joy_right_stick_states); 
-         } else { 
-                 get_joystick_state(joy_axis[SDL_CONTROLLER_AXIS_LEFTX], joy_axis[SDL_CONTROLLER_AXIS_LEFTY], joy_left_stick_states); 
-                 get_joystick_state(joy_axis[SDL_CONTROLLER_AXIS_RIGHTX], joy_axis[SDL_CONTROLLER_AXIS_RIGHTY], joy_right_stick_states); 
-         } 
-   
-         if (joy_left_stick_states[0] == -1 || joy_right_stick_states[0] == -1 || joy_hat_states[0] == -1) 
-                 control_x = -1; 
-   
-         if (joy_left_stick_states[0] == 1 || joy_right_stick_states[0] == 1 || joy_hat_states[0] == 1) 
-                 control_x = 1; 
-   
-         if (joy_left_stick_states[1] == -1 || joy_right_stick_states[1] == -1 || joy_hat_states[1] == -1 || joy_AY_buttons_state == -1) 
-                 control_y = -1; 
-   
-         if (joy_left_stick_states[1] == 1 || joy_right_stick_states[1] == 1 || joy_hat_states[1] == 1 || joy_AY_buttons_state == 1) 
-                 control_y = 1; 
-   
-         if (joy_X_button_state == 1 || 
-                         joy_axis[SDL_CONTROLLER_AXIS_TRIGGERLEFT] > 8000 || 
-                         joy_axis[SDL_CONTROLLER_AXIS_TRIGGERRIGHT] > 8000) 
-         { 
-                 control_shift = -1; 
-         } 
-   
- } 
-   
- // seg000:10EA 
- void __pascal far draw_kid_hp(short curr_hp,short max_hp) { 
-         short drawn_hp_index; 
-         for (drawn_hp_index = curr_hp; drawn_hp_index < max_hp; ++drawn_hp_index) { 
-                 // empty HP 
-                 method_6_blit_img_to_scr(get_image(id_chtab_2_kid, 217), drawn_hp_index * 7, 194, blitters_0_no_transp); 
-         } 
-         for (drawn_hp_index = 0; drawn_hp_index < curr_hp; ++drawn_hp_index) { 
-                 // full HP 
-                 method_6_blit_img_to_scr(get_image(id_chtab_2_kid, 216), drawn_hp_index * 7, 194, blitters_0_no_transp); 
-         } 
- } 
-   
- // seg000:1159 
- void __pascal far draw_guard_hp(short curr_hp,short max_hp) { 
-         short drawn_hp_index; 
-         short guard_charid; 
-         if (chtab_addrs[id_chtab_5_guard] == NULL) return; 
-         guard_charid = Guard.charid; 
-         if (guard_charid != charid_4_skeleton && 
-                 guard_charid != charid_24_mouse && 
-                 // shadow has HP only on level 12 
-                 (guard_charid != charid_1_shadow || current_level == 12) 
-         ) { 
-                 for (drawn_hp_index = curr_hp; drawn_hp_index < max_hp; ++drawn_hp_index) { 
-                         method_6_blit_img_to_scr(chtab_addrs[id_chtab_5_guard]->images[0], 314 - drawn_hp_index * 7, 194, blitters_9_black); 
-                 } 
-                 for (drawn_hp_index = 0; drawn_hp_index < curr_hp; ++drawn_hp_index) { 
-                         method_6_blit_img_to_scr(chtab_addrs[id_chtab_5_guard]->images[0], 314 - drawn_hp_index * 7, 194, blitters_0_no_transp); 
-                 } 
-         } 
- } 
-   
- // seg000:11EC 
- void __pascal far add_life() { 
-         short hpmax = hitp_max; 
-         ++hpmax; 
-         // CusPop: set maximum number of hitpoints (max_hitp_allowed, default = 10) 
- //      if (hpmax > 10) hpmax = 10; // original 
-         if (hpmax > max_hitp_allowed) hpmax = max_hitp_allowed; 
-         hitp_max = hpmax; 
-         set_health_life(); 
- } 
-   
- // seg000:1200 
- void __pascal far set_health_life() { 
-         hitp_delta = hitp_max - hitp_curr; 
- } 
-   
- // seg000:120B 
- void __pascal far draw_hp() { 
-         if (hitp_delta) { 
-                 draw_kid_hp(hitp_curr, hitp_max); 
-         } 
-         if (hitp_curr == 1 && current_level != 15) { 
-                 // blinking hitpoint 
-                 if (rem_tick & 1) { 
-                         draw_kid_hp(1, 0); 
-                 } else { 
-                         draw_kid_hp(0, 1); 
-                 } 
-         } 
-         if (guardhp_delta) { 
-                 draw_guard_hp(guardhp_curr, guardhp_max); 
-         } 
-         if (guardhp_curr == 1) { 
-                 if (rem_tick & 1) { 
-                         draw_guard_hp(1, 0); 
-                 } else { 
-                         draw_guard_hp(0, 1); 
-                 } 
-         } 
- } 
-   
- // seg000:127B 
- void __pascal far do_delta_hp() { 
-         // level 12: if the shadow is hurt, Kid is also hurt 
-         if (Opp.charid == charid_1_shadow && 
-                 current_level == 12 && 
-                 guardhp_delta != 0 
-         ) { 
-                 hitp_delta = guardhp_delta; 
-         } 
-         hitp_curr = MIN(MAX(hitp_curr + hitp_delta, 0), hitp_max); 
-         guardhp_curr = MIN(MAX(guardhp_curr + guardhp_delta, 0), guardhp_max); 
- } 
-   
- byte sound_prio_table[] = { 
-         0x14, 0x1E, 0x23, 0x66, 0x32, 0x37, 0x30, 0x30, 0x4B, 0x50, 0x0A, 
-         0x12, 0x0C, 0x0B, 0x69, 0x6E, 0x73, 0x78, 0x7D, 0x82, 0x91, 0x96, 
-         0x9B, 0xA0, 1, 1, 1, 1, 1, 0x13, 1, 1, 1, 1, 1, 1, 1, 
-         1, 1, 0, 1, 1, 1, 1, 0x87, 0x8C, 0x0F, 0x10, 0x19, 0x16, 1, 
-         0, 1, 1, 1, 1, 1, 0 
- }; 
- byte sound_pcspeaker_exists[] = { 
-         1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 
-         1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
-         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
-         1, 1, 1, 0 
- }; 
-   
- // seg000:12C5 
- void __pascal far play_sound(int sound_id) { 
-         //printf("Would play sound %d\n", sound_id); 
-         if (next_sound < 0 || sound_prio_table[sound_id] <= sound_prio_table[next_sound]) { 
-                 if (NULL == sound_pointers[sound_id]) return; 
-                 if (sound_pcspeaker_exists[sound_id] != 0 || sound_pointers[sound_id]->type != sound_speaker) { 
-                         next_sound = sound_id; 
-                 } 
-         } 
- } 
-   
- // seg000:1304 
- void __pascal far play_next_sound() { 
-         if (next_sound >= 0) { 
-                 if (!check_sound_playing() || 
-                         (sound_interruptible[current_sound] != 0 && sound_prio_table[next_sound] <= sound_prio_table[current_sound]) 
-                 ) { 
-                         current_sound = next_sound; 
-                         play_sound_from_buffer(sound_pointers[current_sound]); 
-                 } 
-         } 
-         next_sound = -1; 
- } 
-   
- // seg000:1353 
- void __pascal far check_sword_vs_sword() { 
-         if (Kid.frame == 167 || Guard.frame == 167) { 
-                 play_sound(sound_10_sword_vs_sword); // sword vs. sword 
-         } 
- } 
-   
- // seg000:136A 
- void __pascal far load_chtab_from_file(int chtab_id,int resource,const char near *filename,int palette_bits) { 
-         //printf("Loading chtab %d, id %d from %s\n",chtab_id,resource,filename); 
-         dat_type* dathandle; 
-         if (chtab_addrs[chtab_id] != NULL) return; 
-         dathandle = open_dat(filename, 0); 
-         chtab_addrs[chtab_id] = load_sprites_from_file(resource, palette_bits, 1); 
-         close_dat(dathandle); 
- } 
-   
- // seg000:13BA 
- void __pascal far free_all_chtabs_from(int first) { 
-         word chtab_id; 
-         free_peels(); 
-         for (chtab_id = first; chtab_id < 10; ++chtab_id) { 
-                 if (chtab_addrs[chtab_id]) { 
-                         free_chtab(chtab_addrs[chtab_id]); 
-                         chtab_addrs[chtab_id] = NULL; 
-                 } 
-         } 
- } 
-   
- // seg009:12EF 
- 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) { 
-         short index; 
-         for (index = min_index; index <= max_index; ++index) { 
-                 image_type* image = load_image(base_id + index + 1, pal_ptr); 
-                 if (image != NULL) chtab_ptr->images[index] = image; 
-         } 
- } 
-   
- byte optgraf_min[] = {0x01, 0x1E, 0x4B, 0x4E, 0x56, 0x65, 0x7F, 0x0A}; 
- byte optgraf_max[] = {0x09, 0x1F, 0x4D, 0x53, 0x5B, 0x7B, 0x8F, 0x0D}; 
- // seg000:13FC 
- void __pascal far load_more_opt_graf(const char *filename) { 
-         // stub 
-         dat_type* dathandle; 
-         dat_shpl_type area; 
-         short graf_index; 
-         dathandle = NULL; 
-         for (graf_index = 0; graf_index < 8; ++graf_index) { 
-                 /*if (...) */ { 
-                         if (dathandle == NULL) { 
-                                 dathandle = open_dat(filename, 0); 
-                                 load_from_opendats_to_area(200, &area, sizeof(area), "pal"); 
-                                 area.palette.row_bits = 0x20; 
-                         } 
-                         load_one_optgraf(chtab_addrs[id_chtab_6_environment], &area.palette, 1200, optgraf_min[graf_index] - 1, optgraf_max[graf_index] - 1); 
-                 } 
-         } 
-         if (dathandle != NULL) { 
-                 close_dat(dathandle); 
-         } 
- } 
-   
- // seg000:148D 
- int __pascal far do_paused() { 
- #ifdef USE_REPLAY 
-         if (replaying && skipping_replay) return 0; 
- #endif 
-   
-         word key; 
-         key = 0; 
-         next_room = 0; 
-         control_shift = 0; 
-         control_y = 0; 
-         control_x = 0; 
-         if (is_joyst_mode) { 
-                 read_joyst_control(); 
-         } else { 
-                 read_keyb_control(); 
-         } 
-         key = process_key(); 
-         if (is_paused) { 
-                 is_paused = 0; 
-                 display_text_bottom("GAME PAUSED"); 
-                 // busy waiting? 
-                 do { 
-                         idle(); 
-                         //request_screen_update(); 
-                 } while (! process_key()); 
-                 erase_bottom_text(1); 
-         } 
-         return key || control_shift; 
- } 
-   
- // seg000:1500 
- void __pascal far read_keyb_control() { 
-   
-         if (key_states[SDL_SCANCODE_UP] || key_states[SDL_SCANCODE_HOME] || key_states[SDL_SCANCODE_PAGEUP] 
-             || key_states[SDL_SCANCODE_KP_8] || key_states[SDL_SCANCODE_KP_7] || key_states[SDL_SCANCODE_KP_9] 
-         ) { 
-                 control_y = -1; 
-         } else if (key_states[SDL_SCANCODE_CLEAR] || key_states[SDL_SCANCODE_DOWN] 
-                    || key_states[SDL_SCANCODE_KP_5] || key_states[SDL_SCANCODE_KP_2] 
-         ) { 
-                 control_y = 1; 
-         } 
-         if (key_states[SDL_SCANCODE_LEFT] || key_states[SDL_SCANCODE_HOME] 
-             || key_states[SDL_SCANCODE_KP_4] || key_states[SDL_SCANCODE_KP_7] 
-         ) { 
-                 control_x = -1; 
-         } else if (key_states[SDL_SCANCODE_RIGHT] || key_states[SDL_SCANCODE_PAGEUP] 
-                    || key_states[SDL_SCANCODE_KP_6] || key_states[SDL_SCANCODE_KP_9] 
-         ) { 
-                 control_x = 1; 
-         } 
-         control_shift = -(key_states[SDL_SCANCODE_LSHIFT] || key_states[SDL_SCANCODE_RSHIFT]); 
-   
-         #ifdef USE_DEBUG_CHEATS 
-         if (cheats_enabled && debug_cheats_enabled) { 
-                 if (key_states[SDL_SCANCODE_RIGHTBRACKET]) ++Char.x; 
-                 else if (key_states[SDL_SCANCODE_LEFTBRACKET]) --Char.x; 
-         } 
-         #endif 
- } 
-   
- // seg000:156D 
- void __pascal far copy_screen_rect(const rect_type far *source_rect_ptr) { 
-         const rect_type* far target_rect_ptr; 
-         rect_type target_rect; 
-         if (upside_down) { 
-                 target_rect_ptr = &target_rect; 
-                 /**target_rect_ptr*/target_rect = *source_rect_ptr; 
-                 /*target_rect_ptr->*/target_rect.top = 192 - source_rect_ptr->bottom; 
-                 /*target_rect_ptr->*/target_rect.bottom = 192 - source_rect_ptr->top; 
-         } else { 
-                 target_rect_ptr = source_rect_ptr; 
-         } 
-         method_1_blit_rect(onscreen_surface_, offscreen_surface, target_rect_ptr, target_rect_ptr, 0); 
- #ifdef USE_LIGHTING 
-         update_lighting(target_rect_ptr); 
- #endif 
- } 
-   
- // seg000:15E9 
- void __pascal far toggle_upside() { 
-         upside_down = ~ upside_down; 
-         need_redraw_because_flipped = 1; 
- } 
-   
- // seg000:15F8 
- void __pascal far feather_fall() { 
-         is_feather_fall = 1; 
-         flash_color = 2; // green 
-         flash_time = 3; 
-         stop_sounds(); 
-         play_sound(sound_39_low_weight); // low weight 
- } 
-   
- // seg000:1618 
- int __pascal far parse_grmode() { 
-         // stub 
-         set_gr_mode(gmMcgaVga); 
-         return gmMcgaVga; 
- } 
-   
- // seg000:172C 
- void __pascal far gen_palace_wall_colors() { 
-         dword old_randseed; 
-         word prev_color; 
-         short row; 
-         short subrow; 
-         word color_base; 
-         short column; 
-         word color; 
-   
-         old_randseed = random_seed; 
-         random_seed = drawn_room; 
-         prandom(1); // discard 
-         for (row = 0; row < 3; row++) { 
-                 for (subrow = 0; subrow < 4; subrow++) { 
-                         if (subrow % 2) { 
-                                 color_base = 0x61; // 0x61..0x64 in subrow 1 and 3 
-                         } else { 
-                                 color_base = 0x66; // 0x66..0x69 in subrow 0 and 2 
-                         } 
-                         prev_color = -1; 
-                         for (column = 0; column <= 10; ++column) { 
-                                 do { 
-                                         color = color_base + prandom(3); 
-                                 } while (color == prev_color); 
-                                 palace_wall_colors[44 * row + 11 * subrow + column] = color; 
-                                 //palace_wall_colors[row][subrow][column] = color; 
-                                 prev_color = color; 
-                         } 
-                 } 
-         } 
-         random_seed = old_randseed; 
- } 
-   
- // data:042E 
- const rect_type rect_titles = {106,24,195,296}; 
-   
- // seg000:17E6 
- void __pascal far show_title() { 
-         word textcolor; 
-         load_opt_sounds(sound_50_story_2_princess, sound_55_story_1_absence); // main theme, story, princess door 
-         textcolor = get_text_color(15, color_15_brightwhite, 0x800); 
-         dont_reset_time = 0; 
-         if(offscreen_surface) free_surface(offscreen_surface); // missing in original 
-         offscreen_surface = make_offscreen_buffer(&screen_rect); 
-         load_title_images(1); 
-         current_target_surface = offscreen_surface; 
-         do_wait(timer_0); 
-   
-         draw_image_2(0 /*main title image*/, chtab_title50, 0, 0, blitters_0_no_transp); 
-         fade_in_2(offscreen_surface, 0x1000); //STUB 
-         method_1_blit_rect(onscreen_surface_, offscreen_surface, &screen_rect, &screen_rect, blitters_0_no_transp); 
-         play_sound_from_buffer(sound_pointers[54]); // main theme 
-         start_timer(timer_0, 0x82); 
-         draw_image_2(1 /*Broderbund Software presents*/, chtab_title50, 96, 106, blitters_0_no_transp); 
-         do_wait(timer_0); 
-   
-         start_timer(timer_0,0xCD); 
-         method_1_blit_rect(onscreen_surface_, offscreen_surface, &rect_titles, &rect_titles, blitters_0_no_transp); 
-         draw_image_2(0 /*main title image*/, chtab_title50, 0, 0, blitters_0_no_transp); 
-         do_wait(timer_0); 
-   
-         start_timer(timer_0,0x41); 
-         method_1_blit_rect(onscreen_surface_, offscreen_surface, &rect_titles, &rect_titles, blitters_0_no_transp); 
-         draw_image_2(0 /*main title image*/, chtab_title50, 0, 0, blitters_0_no_transp); 
-         draw_image_2(2 /*a game by Jordan Mechner*/, chtab_title50, 96, 122, blitters_0_no_transp); 
-         do_wait(timer_0); 
-   
-         start_timer(timer_0,0x10E); 
-         method_1_blit_rect(onscreen_surface_, offscreen_surface, &rect_titles, &rect_titles, blitters_0_no_transp); 
-         draw_image_2(0 /*main title image*/, chtab_title50, 0, 0, blitters_0_no_transp); 
-         do_wait(timer_0); 
-   
-         start_timer(timer_0,0xEB); 
-         method_1_blit_rect(onscreen_surface_, offscreen_surface, &rect_titles, &rect_titles, blitters_0_no_transp); 
-         draw_image_2(0 /*main title image*/, chtab_title50, 0, 0, blitters_0_no_transp); 
-         draw_image_2(3 /*Prince Of Persia*/, chtab_title50, 24, 107, blitters_10h_transp); 
-         draw_image_2(4 /*Copyright 1990 Jordan Mechner*/, chtab_title50, 48, 184, blitters_0_no_transp); 
-         do_wait(timer_0); 
-   
-         method_1_blit_rect(onscreen_surface_, offscreen_surface, &rect_titles, &rect_titles, blitters_0_no_transp); 
-         draw_image_2(0 /*story frame*/, chtab_title40, 0, 0, blitters_0_no_transp); 
-         draw_image_2(1 /*In the Sultan's absence*/, chtab_title40, 24, 25, textcolor); 
-         current_target_surface = onscreen_surface_; 
-         while (check_sound_playing()) { 
-                 idle(); 
-                 do_paused(); 
-         } 
- //      method_1_blit_rect(onscreen_surface_, offscreen_surface, &screen_rect, &screen_rect, blitters_0_no_transp); 
-         play_sound_from_buffer(sound_pointers[sound_55_story_1_absence]); // story 1: In the absence 
-         transition_ltr(); 
-         pop_wait(timer_0, 0x258); 
-         fade_out_2(0x800); 
-         release_title_images(); 
-   
-         load_intro(0, &pv_scene, 0); 
-   
-         load_title_images(1); 
-         current_target_surface = offscreen_surface; 
-         draw_image_2(0 /*story frame*/, chtab_title40, 0, 0, blitters_0_no_transp); 
-         draw_image_2(2 /*Marry Jaffar*/, chtab_title40, 24, 25, textcolor); 
-         fade_in_2(offscreen_surface, 0x800); 
-         draw_image_2(0 /*main title image*/, chtab_title50, 0, 0, blitters_0_no_transp); 
-         draw_image_2(3 /*Prince Of Persia*/, chtab_title50, 24, 107, blitters_10h_transp); 
-         draw_image_2(4 /*Copyright 1990 Jordan Mechner*/, chtab_title50, 48, 184, blitters_0_no_transp); 
-         while (check_sound_playing()) { 
-                 idle(); 
-                 do_paused(); 
-         } 
-         transition_ltr(); 
-         pop_wait(timer_0, 0x78); 
-         draw_image_2(0 /*story frame*/, chtab_title40, 0, 0, blitters_0_no_transp); 
-         draw_image_2(4 /*credits*/, chtab_title40, 24, 26, textcolor); 
-         transition_ltr(); 
-         pop_wait(timer_0, 0x168); 
-         if (hof_count) { 
-                 draw_image_2(0 /*story frame*/, chtab_title40, 0, 0, blitters_0_no_transp); 
-                 draw_image_2(3 /*Prince Of Persia*/, chtab_title50, 24, 24, blitters_10h_transp); 
-                 show_hof(); 
-                 transition_ltr(); 
-                 pop_wait(timer_0, 0xF0); 
-         } 
-         current_target_surface = onscreen_surface_; 
-         while (check_sound_playing()) { 
-                 idle(); 
-                 do_paused(); 
-         } 
-         fade_out_2(0x1800); 
-         free_surface(offscreen_surface); 
-         offscreen_surface = NULL; // added 
-         release_title_images(); 
-         init_game(0); 
- } 
-   
- // seg000:1BB3 
- void __pascal far transition_ltr() { 
-         short position; 
-         rect_type rect; 
-         rect.top = 0; 
-         rect.bottom = 200; 
-         rect.left = 0; 
-         rect.right = 2; 
-         for (position = 0; position < 320; position += 2) { 
-                 method_1_blit_rect(onscreen_surface_, offscreen_surface, &rect, &rect, 0); 
-                 rect.left += 2; 
-                 rect.right += 2; 
-                 pop_wait(timer_1, 0); 
-         } 
- } 
-   
- // seg000:1C0F 
- void __pascal far release_title_images() { 
-         if (chtab_title50) { 
-                 free_chtab(chtab_title50); 
-                 chtab_title50 = NULL; 
-         } 
-         if (chtab_title40) { 
-                 free_chtab(chtab_title40); 
-                 chtab_title40 = NULL; 
-         } 
- } 
-   
- // seg000:1C3A 
- void __pascal far draw_image_2(int id, chtab_type* chtab_ptr, int xpos, int ypos, int blit) { 
-         image_type* source; 
-         image_type* decoded_image; 
-         image_type* mask; 
-         mask = NULL; 
-         if (NULL == chtab_ptr) return; 
-         source = chtab_ptr->images[id]; 
-         decoded_image = source; 
-         if (blit != blitters_0_no_transp && blit != blitters_10h_transp) { 
-                 method_3_blit_mono(decoded_image, xpos, ypos, blitters_0_no_transp, blit); 
-         } else if (blit == blitters_10h_transp) { 
-                 if (graphics_mode == gmCga || graphics_mode == gmHgaHerc) { 
-                         //... 
-                 } else { 
-                         mask = decoded_image; 
-                 } 
-                 draw_image_transp(decoded_image, mask, xpos, ypos); 
-                 if (graphics_mode == gmCga || graphics_mode == gmHgaHerc) { 
-                         free_far(mask); 
-                 } 
-         } else { 
-                 method_6_blit_img_to_scr(decoded_image, xpos, ypos, blit); 
-         } 
- } 
-   
- // seg000:1D2C 
- void __pascal far load_kid_sprite() { 
-         load_chtab_from_file(id_chtab_2_kid, 400, "KID.DAT", 1<<7); 
- } 
-   
- const char* save_file = "PRINCE.SAV"; 
-   
- const char* get_save_path(char* custom_path_buffer, size_t max_len) { 
-         if (!use_custom_levelset) { 
-                 return save_file; 
-         } 
-         // if playing a custom levelset, try to use the mod folder 
-         snprintf(- custom_path_buffer ,-  max_len , "mods/%s/%s",-  levelset_name ,-  save_file  /*PRINCE.SAV*/ );
 
-         return custom_path_buffer; 
- } 
-   
- // seg000:1D45 
- void __pascal far save_game() { 
-         word success; 
-         int handle; 
-         success = 0; 
-         char custom_save_path[POP_MAX_PATH]; 
-         const char* save_path = get_save_path(custom_save_path, sizeof(custom_save_path)); 
-         // no O_TRUNC 
-         handle = open(save_path, O_WRONLY | O_CREAT | O_BINARY, 0600); 
-         if (handle == -1) goto loc_1DB8; 
-         if (write(handle, &rem_min, 2) == 2) goto loc_1DC9; 
-         loc_1D9B: 
-         close(handle); 
-         if (!success) { 
-                 unlink(save_path); 
-         } 
-         loc_1DB8: 
-         if (!success) goto loc_1E18; 
-         display_text_bottom("GAME SAVED"); 
-         goto loc_1E2E; 
-         loc_1DC9: 
-         if (write(handle, &rem_tick, 2) != 2) goto loc_1D9B; 
-         if (write(handle, ¤t_level, 2) != 2) goto loc_1D9B; 
-         if (write(handle, &hitp_beg_lev, 2) != 2) goto loc_1D9B; 
-         success = 1; 
-         goto loc_1D9B; 
-         loc_1E18: 
-         display_text_bottom("UNABLE TO SAVE GAME"); 
-         //play_sound_from_buffer(&sound_cant_save); 
-         loc_1E2E: 
-         text_time_remaining = 24; 
- } 
-   
- // seg000:1E38 
- short __pascal far load_game() { 
-         int handle; 
-         word success; 
-         success = 0; 
-         char custom_save_path[POP_MAX_PATH]; 
-         const char* save_path = get_save_path(custom_save_path, sizeof(custom_save_path)); 
-         handle = open(save_path, O_RDONLY | O_BINARY); 
-         if (handle == -1) goto loc_1E99; 
-         if (read(handle, &rem_min, 2) == 2) goto loc_1E9E; 
-         loc_1E8E: 
-         close(handle); 
-         loc_1E99: 
-         return success; 
-         loc_1E9E: 
-         if (read(handle, &rem_tick, 2) != 2) goto loc_1E8E; 
-         if (read(handle, &start_level, 2) != 2) goto loc_1E8E; 
-         if (read(handle, &hitp_beg_lev, 2) != 2) goto loc_1E8E; 
- #ifdef USE_COPYPROT 
-         if (enable_copyprot && copyprot_level > 0) { 
-                 copyprot_level = start_level; 
-         } 
- #endif 
-         success = 1; 
-         dont_reset_time = 1; 
-         goto loc_1E8E; 
- } 
-   
- // seg000:1F02 
- void __pascal far clear_screen_and_sounds() { 
-         short index; 
-         stop_sounds(); 
-         current_target_surface = rect_sthg(onscreen_surface_, &screen_rect); 
-   
-         is_cutscene = 0; 
-         peels_count = 0; 
-         // should these be freed? 
-         for (index = 2; index < 10; ++index) { 
-                 if (chtab_addrs[index]) { 
-                         // Original code does not free these? 
-                         free_chtab(chtab_addrs[index]); 
-                         chtab_addrs[index] = NULL; 
-                 } 
-         } 
-         /* //Don't free sounds. 
-         for (index = 44; index < 57; ++index) { 
-                 //continue; // don't release sounds? modern machines have enough memory 
-                 free_sound(sound_pointers[index]); // added 
-                 sound_pointers[index] = NULL; 
-         } 
-         */ 
-         current_level = -1; 
- } 
-   
- // seg000:1F7B 
- void __pascal far parse_cmdline_sound() { 
-         // stub 
-         sound_flags |= sfDigi; 
- } 
-   
- // seg000:226D 
- void __pascal far free_optional_sounds() { 
-         /* //Don't free sounds. 
-         int sound_id; 
-         for (sound_id = 44; sound_id < 57; ++sound_id) { 
-                 free_sound(sound_pointers[sound_id]); 
-                 sound_pointers[sound_id] = NULL; 
-         } 
-         */ 
-         // stub 
- } 
-   
- const byte tbl_snd_is_music[] = { 
-                 0,0,0,0,0,0,0,0,0,0, //9 
-                 0,0,0,0,0,0,0,0,0,0, //19 
-                 0,0,0,0,1,1,1,1,1,1, //29 
-                 1,0,1,1,1,1,1,1,0,1, //39 
-                 1,1,0,1,0,0,0,0,0,0, //49 
-                 1,0,1,1,1,1,1 
- }; 
-   
- void reload_non_music_sounds() { 
-         int i; 
-         for (i = 0; i < COUNT(tbl_snd_is_music); ++i) { 
-                 if (!tbl_snd_is_music[i]) { 
-                         free_sound(sound_pointers[i]); 
-                         sound_pointers[i] = NULL; 
-                 } 
-         } 
-         load_sounds(0, 43); 
-         load_opt_sounds(44, 56); 
- } 
-   
- // seg000:22BB 
- void __pascal far free_optsnd_chtab() { 
-         free_optional_sounds(); 
-         free_all_chtabs_from(id_chtab_3_princessinstory); 
- } 
-   
- // seg000:22C8 
- void __pascal far load_title_images(int bgcolor) { 
-         dat_type* dathandle; 
-         dathandle = open_dat("TITLE.DAT", 0); 
-         chtab_title40 = load_sprites_from_file(40, 1<<11, 1); 
-         chtab_title50 = load_sprites_from_file(50, 1<<12, 1); 
-         close_dat(dathandle); 
-         if (graphics_mode == gmMcgaVga) { 
-                 // background of text frame 
-                 SDL_Color color; 
-                 if (bgcolor) { 
-                         // RGB(4,0,18h) = #100060 = dark blue 
-                         set_pal((find_first_pal_row(1<<11) << 4) + 14, 0x04, 0x00, 0x18, 1); 
-                         color.r = 0x10; 
-                         color.g = 0x00; 
-                         color.b = 0x60; 
-                         color.a = 0xFF; 
-                 } else { 
-                         // RGB(20h,0,0) = #800000 = dark red 
-                         set_pal((find_first_pal_row(1<<11) << 4) + 14, 0x20, 0x00, 0x00, 1); 
-                         color.r = 0x80; 
-                         color.g = 0x00; 
-                         color.b = 0x00; 
-                         color.a = 0xFF; 
-                 } 
-                 if (NULL != chtab_title40) { 
-                         SDL_SetPaletteColors(chtab_title40->images[0]->format->palette, &color, 14, 1); 
-                 } 
-         } else if (graphics_mode == gmEga || graphics_mode == gmTga) { 
-                 // ... 
-         } 
- } 
-   
- #ifdef USE_COPYPROT 
- // data:017A 
- 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}; 
- // data:012A 
- 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}; 
- // data:00DA 
- 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}; 
- #endif 
-   
- // seg000:23F4 
- void __pascal far show_copyprot(int where) { 
- #ifdef USE_COPYPROT 
-         char sprintf_temp[140]; 
-         if (current_level != 15) return; 
-         if (where) { 
-                 if (text_time_remaining || is_cutscene) return; 
-                 text_time_total = 1188; 
-                 text_time_remaining = 1188; 
-                 is_show_time = 0; 
-                 snprintf(- sprintf_temp , sizeof(- sprintf_temp ),
 
-                         "WORD %d LINE %d PAGE %d", 
-                         copyprot_word[copyprot_idx], copyprot_line[copyprot_idx], copyprot_page[copyprot_idx]); 
-                 display_text_bottom(sprintf_temp); 
-         } else { 
-                 snprintf(- sprintf_temp , sizeof(- sprintf_temp ),
 
-                         "Drink potion matching the first letter of Word %d on Line %d\n" 
-                         "of Page %d of the manual.", 
-                         copyprot_word[copyprot_idx], copyprot_line[copyprot_idx], copyprot_page[copyprot_idx]); 
-                 show_dialog(sprintf_temp); 
-         } 
- #endif 
- } 
-   
- // seg000:2489 
- void __pascal far show_loading() { 
-         show_text(&screen_rect, 0, 0, "Loading. . . ."); 
- } 
-   
- // data:42C4 
- word which_quote; 
-   
- char const * const tbl_quotes[2] = { 
- "\"(****/****) Incredibly realistic. . . The " 
- "adventurer character actually looks human as he " 
- "runs, jumps, climbs, and hangs from ledges.\"\n" 
- "\n" 
- "                                  Computer Entertainer\n" 
- "\n" 
- "\n" 
- "\n" 
- "\n" 
- "\"A tremendous achievement. . . Mechner has crafted " 
- "the smoothest animation ever seen in a game of this " 
- "type.\n" 
- "\n" 
- "\"PRINCE OF PERSIA is the STAR WARS of its field.\"\n" 
- "\n" 
- "                                  Computer Gaming World", 
- "\"An unmitigated delight. . . comes as close to " 
- "(perfection) as any arcade game has come in a long, " 
- "long time. . . what makes this game so wonderful (am " 
- "I gushing?) is that the little onscreen character " 
- "does not move like a little onscreen character -- he " 
- "moves like a person.\"\n" 
- "\n" 
- "                                      Nibble" 
- }; 
-   
- // seg000:249D 
- void __pascal far show_quotes() { 
-         //start_timer(timer_0,0); 
-         //remove_timer(timer_0); 
-         if (demo_mode && need_quotes) { 
-                 draw_rect(&screen_rect, 0); 
-                 show_text(&screen_rect, -1, 0, tbl_quotes[which_quote]); 
-                 which_quote = !which_quote; 
-                 start_timer(timer_0,0x384); 
-         } 
-         need_quotes = 0; 
- } 
-   
- const rect_type splash_text_1_rect = {0, 0, 50, 320}; 
- const rect_type splash_text_2_rect = {50, 0, 200, 320}; 
-   
- const char* splash_text_1 = "SDLPoP " SDLPOP_VERSION; 
- const char* splash_text_2 = 
-                 "To quick save/load, press F6/F9 in-game.\n" 
-                 "\n" 
- #ifdef USE_REPLAY 
-                 "To record replays, press Ctrl+Tab in-game.\n" 
-                 "To view replays, press Tab on the title screen.\n" 
-                 "\n" 
- #endif 
-                 "Edit game.ini to customize SDLPoP.\n" 
-                 "Mods also work with SDLPoP.\n" 
-                 "\n" 
-                 "For more information, read doc/Readme.txt.\n" 
-                 "Questions? Visit http://forum.princed.org\n" 
-                 "\n" 
-                 "Press any key to continue..."; 
-   
- void show_splash() { 
-         if (!enable_info_screen || start_level >= 0) return; 
-         screen_updates_suspended = 0; 
-         current_target_surface = onscreen_surface_; 
-         draw_rect(&screen_rect, 0); 
-         show_text_with_color(&splash_text_1_rect, 0, 0, splash_text_1, color_15_brightwhite); 
-         show_text_with_color(&splash_text_2_rect, 0, -1, splash_text_2, color_7_lightgray); 
-   
-         int key = 0; 
-         do { 
-                 idle(); 
-                 key = key_test_quit(); 
-   
-                 if (joy_hat_states[0] != 0 || joy_X_button_state != 0 || joy_AY_buttons_state != 0 || joy_B_button_state != 0) { 
-                         joy_hat_states[0] = 0; 
-                         joy_AY_buttons_state = 0; 
-                         joy_X_button_state = 0; 
-                         joy_B_button_state = 0; 
-                         key_states[SDL_SCANCODE_LSHIFT] = 1; // close the splash screen using the gamepad 
-                 } 
-   
-         } while(key == 0 && !(key_states[SDL_SCANCODE_LSHIFT] || key_states[SDL_SCANCODE_RSHIFT])); 
-   
-         if ((key & WITH_CTRL) || (enable_quicksave && key == SDL_SCANCODE_F9) || (enable_replay && key == SDL_SCANCODE_TAB)) { 
-                 extern int last_key_scancode; // defined in seg009.c 
-                 last_key_scancode = key; // can immediately do Ctrl+L, etc from the splash screen 
-         } 
-         key_states[SDL_SCANCODE_LSHIFT] = 0; // don't immediately start the game if shift was pressed! 
-         key_states[SDL_SCANCODE_RSHIFT] = 0; 
- } 
-