static giblorb_result_t handleBlorb (strid_t stream) { giblorb_err_t err; giblorb_result_t blorbres; giblorb_map_t *map; err = giblorb_set_resource_map (stream); switch (err) { case giblorb_err_None: break; case giblorb_err_CompileTime: fatalError ("Can't read the Blorb file because something is compiled wrong in the Blorb library."); case giblorb_err_Alloc: fatalError ("Can't read the Blorb file because there isn't enough memory available."); case giblorb_err_Read: fatalError ("Can't read data from the Blorb file."); case giblorb_err_Format: fatalError ("Can't read the Blorb file because it seems to be corrupted."); default: fatalError ("Can't read the Blorb file because an unknown error occurred."); } map = giblorb_get_resource_map(); if (map == NULL) fatalError ("Can't find the Blorb file's resource map."); err = giblorb_load_resource(map, giblorb_method_FilePos, &blorbres, giblorb_ID_Exec, 0); if (err) fatalError ("This Blorb file does not contain an executable Glulx chunk."); if (blorbres.chunktype != giblorb_make_id('G', 'L', 'U', 'L')) fatalError ("This Blorb file contains an executable chunk, but it is not a Glulx file."); return blorbres; }
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 */
giblorb_err_t wrap_gib_set_resource_map(strid_t file) { return giblorb_set_resource_map(file); }