void z_restart (void) { static bool first_restart = TRUE; flush_buffer (); os_restart_game (RESTART_BEGIN); seed_random (0); if (!first_restart) { fseek (story_fp, blorb_ofs, SEEK_SET); if (fread (zmp, 1, h_dynamic_size, story_fp) != h_dynamic_size) os_fatal ("Story file read error"); } else first_restart = FALSE; restart_header (); restart_screen (); sp = fp = stack + STACK_SIZE; frame_count = 0; if (h_version != V6) { long pc = (long) h_start_pc; SET_PC (pc); } else call (h_start_pc, 0, NULL, 0); os_restart_game (RESTART_END); }/* z_restart */
/* get a character. Exit with no fuss on EOF. */ static int xgetchar(void) { int c = getchar(); if (c == EOF) { if (feof(stdin)) { fprintf(stderr, "\nEOT\n"); exit(0); } os_fatal(strerror(errno)); } return c; }
static void bt_sighandler(int sig, siginfo_t *info, void *secret) { void *trace[16]; char *nam; int i, trace_size = 0; // ucontext_t *uc = (ucontext_t *)secret; if (sig == SIGINT) os_fatal("Emergency exit!\n\n(Signal SIGINT received)"); /* Do something useful with siginfo_t */ printf("\nInterpreter bug!\nSignal %d ", sig); if ((nam = getsigname(sig))) printf("[%s] ",nam); // printf("from %p", (void *)uc->uc_mcontext.gregs[_PROG_COUNTER]); if (sig == SIGSEGV) printf(" [faulty address is %p]",info->si_addr); printf("\n"); trace_size = backtrace(trace, 16); /* overwrite sigaction with caller's address */ // trace[1] = (void *) uc->uc_mcontext.gregs[_PROG_COUNTER]; /* skip first stack frame (points here) */ printf("Backtrace:\n"); // messages = backtrace_symbols(trace, trace_size); // for (i=1; i<trace_size; ++i) // printf("[bt] %s\n", messages[i]); for (i=1;i<trace_size;i++) { printf(" "); fflush(stdout); backtrace_symbols_fd(trace+i, 1,fileno(stdout)); } exit(0); }
void runtime_error (int errnum) { int wasfirst; if (errnum <= 0 || errnum > ERR_NUM_ERRORS) return; if (f_setup.err_report_mode == ERR_REPORT_FATAL || (!f_setup.ignore_errors && errnum <= ERR_MAX_FATAL)) { flush_buffer (); os_fatal (err_messages[errnum - 1]); return; } wasfirst = (error_count[errnum - 1] == 0); error_count[errnum - 1]++; if ((f_setup.err_report_mode == ERR_REPORT_ALWAYS) || (f_setup.err_report_mode == ERR_REPORT_ONCE && wasfirst)) { long pc; GET_PC (pc); print_string ("Warning: "); print_string (err_messages[errnum - 1]); print_string (" (PC = "); print_long (pc, 16); print_char (')'); if (f_setup.err_report_mode == ERR_REPORT_ONCE) { print_string (" (will ignore further occurrences)"); } else { print_string (" (occurence "); print_long (error_count[errnum - 1], 10); print_char (')'); } new_line (); } } /* report_error */
void os_init_screen (void) { /*trace(TRACE_CALLS);*/ if (initscr() == NULL) { /* Set up curses */ os_fatal("Unable to initialize curses. Maybe your $TERM setting is bad."); exit(1); } u_setup.curses_active = 1; /* Let os_fatal know curses is running */ cbreak(); /* Raw input mode, no line processing */ noecho(); /* No input echo */ nonl(); /* No newline translation */ intrflush(stdscr, TRUE); /* Flush output on interrupt */ keypad(stdscr, TRUE); /* Enable the keypad and function keys */ scrollok(stdscr, FALSE); /* No scrolling unless explicitly asked for */ if (h_version == V3 && u_setup.tandy_bit != 0) h_config |= CONFIG_TANDY; if (h_version == V3) h_config |= CONFIG_SPLITSCREEN; if (h_version >= V4) h_config |= CONFIG_BOLDFACE | CONFIG_EMPHASIS | CONFIG_FIXED | CONFIG_TIMEDINPUT; if (h_version >= V5) h_flags &= ~(GRAPHICS_FLAG | MOUSE_FLAG | MENU_FLAG); #ifdef NO_SOUND if (h_version >= V5) h_flags &= ~SOUND_FLAG; if (h_version == V3) h_flags &= ~OLD_SOUND_FLAG; #else if ((h_version >= 5) && (h_flags & SOUND_FLAG)) h_flags |= SOUND_FLAG; if ((h_version == 3) && (h_flags & OLD_SOUND_FLAG)) h_flags |= OLD_SOUND_FLAG; if ((h_version == 6) && (f_setup.sound != 0)) h_config |= CONFIG_SOUND; #endif if (h_version >= V5 && (h_flags & UNDO_FLAG)) if (f_setup.undo_slots == 0) h_flags &= ~UNDO_FLAG; getmaxyx(stdscr, h_screen_rows, h_screen_cols); if (u_setup.screen_height != -1) h_screen_rows = u_setup.screen_height; if (u_setup.screen_width != -1) h_screen_cols = u_setup.screen_width; h_screen_width = h_screen_cols; h_screen_height = h_screen_rows; h_font_width = 1; h_font_height = 1; /* Must be after screen dimensions are computed. */ if (h_version == V6) { if (unix_init_pictures()) h_config |= CONFIG_PICTURES; else h_flags &= ~GRAPHICS_FLAG; } /* Use the ms-dos interpreter number for v6, because that's the * kind of graphics files we understand. Otherwise, use DEC. */ h_interpreter_number = h_version == 6 ? INTERP_MSDOS : INTERP_DEC_20; h_interpreter_version = 'F'; #ifdef COLOR_SUPPORT /* Enable colors if the terminal supports them, the user did not * disable colors, and the game or user requested colors. User * requests them by specifying a foreground or background. */ u_setup.color_enabled = (has_colors() && !u_setup.disable_color && (((h_version >= 5) && (h_flags & COLOUR_FLAG)) || (u_setup.foreground_color != -1) || (u_setup.background_color != -1))); /* Maybe we don't want to muck about with changing $TERM to * xterm-color which some supposedly current Unicies still don't * understand. */ if (u_setup.force_color) u_setup.color_enabled = TRUE; if (u_setup.color_enabled) { h_config |= CONFIG_COLOUR; h_flags |= COLOUR_FLAG; /* FIXME: beyond zork handling? */ start_color(); h_default_foreground = (u_setup.foreground_color == -1) ? FOREGROUND_DEF : u_setup.foreground_color; h_default_background = (u_setup.background_color ==-1) ? BACKGROUND_DEF : u_setup.background_color; } else #endif /* COLOR_SUPPORT */ { /* Set these per spec 8.3.2. */ h_default_foreground = WHITE_COLOUR; h_default_background = BLACK_COLOUR; if (h_flags & COLOUR_FLAG) h_flags &= ~COLOUR_FLAG; } os_set_colour(h_default_foreground, h_default_background); os_erase_area(1, 1, h_screen_rows, h_screen_cols, 0); }/* os_init_screen */
void z_restore (void) { FILE *gfp; zword success = 0; if (zargc != 0) { /* Get the file name */ /* Open auxilary file */ if ((gfp = frotzopenprompt(FILE_LOAD_AUX)) == NULL) goto finished; /* Load auxilary file */ success = fread (zmp + zargs[0], 1, zargs[1], gfp); /* Close auxilary file */ fclose (gfp); } else { long pc; zword release; zword addr; int i; /* Open game file */ if ((gfp = frotzopenprompt(FILE_RESTORE)) == NULL) goto finished; if (f_setup.save_quetzal) { success = restore_quetzal (gfp, story_fp, blorb_ofs); } else { /* Load game file */ release = (unsigned) fgetc (gfp) << 8; release |= fgetc (gfp); (void) fgetc (gfp); (void) fgetc (gfp); /* Check the release number */ if (release == h_release) { pc = (long) fgetc (gfp) << 16; pc |= (unsigned) fgetc (gfp) << 8; pc |= fgetc (gfp); SET_PC (pc); sp = stack + (fgetc (gfp) << 8); sp += fgetc (gfp); fp = stack + (fgetc (gfp) << 8); fp += fgetc (gfp); for (i = (int) (sp - stack); i < STACK_SIZE; i++) { stack[i] = (unsigned) fgetc (gfp) << 8; stack[i] |= fgetc (gfp); } fseek (story_fp, blorb_ofs, SEEK_SET); for (addr = 0; addr < h_dynamic_size; addr++) { int skip = fgetc (gfp); for (i = 0; i < skip; i++) zmp[addr++] = fgetc (story_fp); zmp[addr] = fgetc (gfp); (void) fgetc (story_fp); } /* Check for errors */ if (ferror (gfp) || ferror (story_fp) || addr != h_dynamic_size) success = -1; else /* Success */ success = 2; } else print_string ("Invalid save file\n"); } if ((short) success >= 0) { /* Close game file */ fclose (gfp); if ((short) success > 0) { zbyte old_screen_rows; zbyte old_screen_cols; /* In V3, reset the upper window. */ if (h_version == V3) split_window (0); LOW_BYTE (H_SCREEN_ROWS, old_screen_rows); LOW_BYTE (H_SCREEN_COLS, old_screen_cols); /* Reload cached header fields. */ restart_header (); /* * Since QUETZAL files may be saved on many different machines, * the screen sizes may vary a lot. Erasing the status window * seems to cover up most of the resulting badness. */ if (h_version > V3 && h_version != V6 && (h_screen_rows != old_screen_rows || h_screen_cols != old_screen_cols)) erase_window (1); } } else os_fatal ("Error reading save file"); } finished: if (h_version <= V3) branch (success); else store (success); }/* z_restore */
void init_memory (void) { long size; zword addr; unsigned n; int i, j; static struct { enum story story_id; zword release; zbyte serial[6]; } records[] = { { SHERLOCK, 21, "871214" }, { SHERLOCK, 26, "880127" }, { BEYOND_ZORK, 47, "870915" }, { BEYOND_ZORK, 49, "870917" }, { BEYOND_ZORK, 51, "870923" }, { BEYOND_ZORK, 57, "871221" }, { ZORK_ZERO, 296, "881019" }, { ZORK_ZERO, 366, "890323" }, { ZORK_ZERO, 383, "890602" }, { ZORK_ZERO, 393, "890714" }, { SHOGUN, 292, "890314" }, { SHOGUN, 295, "890321" }, { SHOGUN, 311, "890510" }, { SHOGUN, 322, "890706" }, { ARTHUR, 54, "890606" }, { ARTHUR, 63, "890622" }, { ARTHUR, 74, "890714" }, { JOURNEY, 26, "890316" }, { JOURNEY, 30, "890322" }, { JOURNEY, 77, "890616" }, { JOURNEY, 83, "890706" }, { LURKING_HORROR, 203, "870506" }, { LURKING_HORROR, 219, "870912" }, { LURKING_HORROR, 221, "870918" }, { UNKNOWN, 0, "------" } }; /* Open story file */ { giblorb_map_t *map; giblorb_result_t res; char magic[4] = "XXXX"; strid_t file; file = game_file_stream; fread(magic, 1, 4, file); if (!memcmp(magic, "FORM", 4)) { if (giblorb_set_resource_map(file)) os_fatal("This Blorb file seems to be invalid."); map = giblorb_get_resource_map(); if (giblorb_load_resource(map, giblorb_method_FilePos, &res, giblorb_ID_Exec, 0)) os_fatal("This Blorb file does not contain an executable chunk."); if (res.chunktype != giblorb_make_id('Z','C','O','D')) os_fatal("This Blorb file contains an executable chunk, but it is not a Z-code file."); story_fp = file; blorb_ofs = res.data.startpos; blorb_len = res.length; } else { story_fp = file; blorb_ofs = 0; fseek(story_fp, 0, SEEK_END); blorb_len = ftell(story_fp); } } if (blorb_len < 64) os_fatal("This file is too small to be a Z-code file."); /* Allocate memory for story header */ if ((zmp = (zbyte *) malloc (64)) == NULL) os_fatal ("Out of memory"); /* Load header into memory */ fseek(story_fp, blorb_ofs, 0); if (fread (zmp, 1, 64, story_fp) != 64) os_fatal ("Story file read error"); /* Copy header fields to global variables */ LOW_BYTE (H_VERSION, h_version); if (h_version < V1 || h_version > V8) os_fatal ("Unknown Z-code version"); if (h_version == V6) os_fatal ("Cannot play Z-code version 6"); LOW_BYTE (H_CONFIG, h_config); if (h_version == V3 && (h_config & CONFIG_BYTE_SWAPPED)) os_fatal ("Byte swapped story file"); LOW_WORD (H_RELEASE, h_release); LOW_WORD (H_RESIDENT_SIZE, h_resident_size); LOW_WORD (H_START_PC, h_start_pc); LOW_WORD (H_DICTIONARY, h_dictionary); LOW_WORD (H_OBJECTS, h_objects); LOW_WORD (H_GLOBALS, h_globals); LOW_WORD (H_DYNAMIC_SIZE, h_dynamic_size); LOW_WORD (H_FLAGS, h_flags); for (i = 0, addr = H_SERIAL; i < 6; i++, addr++) LOW_BYTE (addr, h_serial[i]); /* Auto-detect buggy story files that need special fixes */ story_id = UNKNOWN; for (i = 0; records[i].story_id != UNKNOWN; i++) { if (h_release == records[i].release) { for (j = 0; j < 6; j++) if (h_serial[j] != records[i].serial[j]) goto no_match; story_id = records[i].story_id; } no_match: ; /* null statement */ } LOW_WORD (H_ABBREVIATIONS, h_abbreviations); LOW_WORD (H_FILE_SIZE, h_file_size); /* Calculate story file size in bytes */ if (h_file_size != 0) { story_size = (long) 2 * h_file_size; if (h_version >= V4) story_size *= 2; if (h_version >= V6) story_size *= 2; } else { /* some old games lack the file size entry */ story_size = blorb_len; } LOW_WORD (H_CHECKSUM, h_checksum); LOW_WORD (H_ALPHABET, h_alphabet); LOW_WORD (H_FUNCTIONS_OFFSET, h_functions_offset); LOW_WORD (H_STRINGS_OFFSET, h_strings_offset); LOW_WORD (H_TERMINATING_KEYS, h_terminating_keys); LOW_WORD (H_EXTENSION_TABLE, h_extension_table); /* Zork Zero Macintosh doesn't have the graphics flag set */ if (story_id == ZORK_ZERO && h_release == 296) h_flags |= GRAPHICS_FLAG; /* Adjust opcode tables */ if (h_version <= V4) { op0_opcodes[0x09] = z_pop; op1_opcodes[0x0f] = z_not; } else { op0_opcodes[0x09] = z_catch; op1_opcodes[0x0f] = z_call_n; } /* Allocate memory for story data */ if ((zmp = (zbyte *) realloc (zmp, story_size)) == NULL) os_fatal ("Out of memory"); /* Load story file in chunks of 32KB */ n = 0x8000; for (size = 64; size < story_size; size += n) { if (story_size - size < 0x8000) n = (unsigned) (story_size - size); SET_PC (size); if (fread (pcp, 1, n, story_fp) != n) os_fatal ("Story file read error"); } /* Read header extension table */ hx_table_size = get_header_extension (HX_TABLE_SIZE); hx_unicode_table = get_header_extension (HX_UNICODE_TABLE); }/* init_memory */
static void myhandler( int s) { resethandlers(); os_fatal("Signal %d received %s",s,signame(s)); }
void __stack_chk_fail(void) { os_fatal("stack_chk_fail"); }
void abort() { os_fatal("abort()"); }