Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
0
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 */
Ejemplo n.º 3
0
int glkunix_startup_code(glkunix_startup_t *data)
{
  /* It turns out to be more convenient if we return TRUE from here, even 
     when an error occurs, and display an error in glk_main(). */
  int ix;
  char *filename = NULL;
  char *gameinfofilename = NULL;
  int gameinfoloaded = FALSE;
  unsigned char buf[12];
  int res;

#ifdef GARGLK
  char *cx;
#endif

#ifdef GARGLK
  garglk_set_program_name("Glulxe 0.5.2");
  garglk_set_program_info("Glulxe 0.5.2 by Andrew Plotkin");
#endif

  /* Parse out the arguments. They've already been checked for validity,
     and the library-specific ones stripped out.
     As usual for Unix, the zeroth argument is the executable name. */
  for (ix=1; ix<data->argc; ix++) {

#if VM_PROFILING
    if (!strcmp(data->argv[ix], "--profile")) {
      ix++;
      if (ix<data->argc) {
        strid_t profstr = glkunix_stream_open_pathname_gen(data->argv[ix], TRUE, FALSE, 1);
        if (!profstr) {
          init_err = "Unable to open profile output file.";
          init_err2 = data->argv[ix];
          return TRUE;
        }
        setup_profile(profstr, NULL);
      }
      continue;
    }
    if (!strcmp(data->argv[ix], "--profcalls")) {
      profile_set_call_counts(TRUE);
      continue;
    }
#endif /* VM_PROFILING */

#if VM_DEBUGGER
    if (!strcmp(data->argv[ix], "--gameinfo")) {
      ix++;
      if (ix<data->argc) {
        gameinfofilename = data->argv[ix];
      }
      continue;
    }
    if (!strcmp(data->argv[ix], "--cpu")) {
      debugger_track_cpu(TRUE);
      continue;
    }
    if (!strcmp(data->argv[ix], "--starttrap")) {
      debugger_set_start_trap(TRUE);
      continue;
    }
    if (!strcmp(data->argv[ix], "--quittrap")) {
      debugger_set_quit_trap(TRUE);
      continue;
    }
    if (!strcmp(data->argv[ix], "--crashtrap")) {
      debugger_set_crash_trap(TRUE);
      continue;
    }
#endif /* VM_DEBUGGER */

    if (filename) {
      init_err = "You must supply exactly one game file.";
      return TRUE;
    }
    filename = data->argv[ix];
  }

  if (!filename) {
    init_err = "You must supply the name of a game file.";
    return TRUE;
  }
    
  gamefile = glkunix_stream_open_pathname(filename, FALSE, 1);
  if (!gamefile) {
    init_err = "The game file could not be opened.";
    init_err2 = filename;
    return TRUE;
  }

#ifdef GARGLK
  cx = strrchr(data->argv[1], '/');
  if (!cx) cx = strrchr(data->argv[1], '\\');
  garglk_set_story_name(cx ? cx + 1 : data->argv[1]);
#endif

#if VM_DEBUGGER
  if (gameinfofilename) {
    strid_t debugstr = glkunix_stream_open_pathname_gen(gameinfofilename, FALSE, FALSE, 1);
    if (!debugstr) {
      nonfatal_warning("Unable to open gameinfo file for debug data.");
    }
    else {
      int bres = debugger_load_info_stream(debugstr);
      glk_stream_close(debugstr, NULL);
      if (!bres)
        nonfatal_warning("Unable to parse game info.");
      else
        gameinfoloaded = TRUE;
    }
  }

  /* Report debugging available, whether a game info file is loaded or not. */
  gidebug_debugging_available(debugger_cmd_handler, debugger_cycle_handler);
#endif /* VM_DEBUGGER */

  /* Now we have to check to see if it's a Blorb file. */

  glk_stream_set_position(gamefile, 0, seekmode_Start);
  res = glk_get_buffer_stream(gamefile, (char *)buf, 12);
  if (!res) {
    init_err = "The data in this stand-alone game is too short to read.";
    return TRUE;
  }
    
  if (buf[0] == 'G' && buf[1] == 'l' && buf[2] == 'u' && buf[3] == 'l') {
    /* Load game directly from file. */
    locate_gamefile(FALSE);

    return TRUE;
  }
  else if (buf[0] == 'F' && buf[1] == 'O' && buf[2] == 'R' && buf[3] == 'M'
    && buf[8] == 'I' && buf[9] == 'F' && buf[10] == 'R' && buf[11] == 'S') {
    /* Load game from a chunk in the Blorb file. */
    locate_gamefile(TRUE);

#if VM_DEBUGGER
    /* Load the debug info from the Blorb, if it wasn't loaded from a file. */
    if (!gameinfoloaded) {
      glui32 giblorb_ID_Dbug = giblorb_make_id('D', 'b', 'u', 'g');
      giblorb_err_t err;
      giblorb_result_t blorbres;
      err = giblorb_load_chunk_by_type(giblorb_get_resource_map(), 
        giblorb_method_FilePos, 
        &blorbres, giblorb_ID_Dbug, 0);
      if (!err) {
        int bres = debugger_load_info_chunk(gamefile, blorbres.data.startpos, blorbres.length);
        if (!bres)
          nonfatal_warning("Unable to parse game info.");
        else
          gameinfoloaded = TRUE;
      }
    }
#endif /* VM_DEBUGGER */
    return TRUE;
  }
  else {
    init_err = "This is neither a Glulx game file nor a Blorb file "
      "which contains one.";
    return TRUE;
  }
}
Ejemplo n.º 4
0
// Get the identifier for graphics supported for this loader
glui32 CWinGlkJPEGGraphicLoader::GetIdentifier(void)
{
  return giblorb_make_id('J','P','E','G');
}
Ejemplo n.º 5
0
// Get the identifier for sounds supported for this loader
glui32 CWinGlkOGGSoundLoader::GetIdentifier(void)
{
  return giblorb_make_id('O','G','G','V');
}