Exemplo n.º 1
0
static int detect_and_add_z_file(char *filename, char *blorb_filename,
    struct babel_info *babel, struct z_story_list *story_list)
{
  z_file *infile;
  uint8_t buf[30];
  uint32_t val;
  char serial[7];
  int version;
  uint16_t checksum;
  uint16_t release;
  struct babel_story_info *b_info = NULL;
  char *title;
  char *author;
  char *language;
  char *description;
  char *ptr, *ptr2;
  int length;
  time_t storyfile_timestamp;
  char *empty_string = "";
  struct z_story_list_entry *entry;
  int chunk_length = -1;
  struct babel_info *file_babel = NULL;
  bool file_is_zblorb;
  char *cwd = NULL;
  char *abs_filename = NULL;

  if (filename == NULL)
    return -1;

  if (filename[0] != '/')
  {
    cwd = fsi->get_cwd();
    abs_filename = fizmo_malloc(strlen(cwd) + strlen(filename) + 2);
    sprintf(abs_filename, "%s/%s", cwd, filename);
  }
  else
    abs_filename = filename;

  if ((infile = fsi->openfile(abs_filename, FILETYPE_DATA, FILEACCESS_READ))
      == NULL)
  {
    if (cwd != NULL)
    {
      free(cwd);
      free(abs_filename);
    }
    return -1;
  }

  if ((storyfile_timestamp = fsi->get_last_file_mod_timestamp(infile)) < 0)
  {
    fsi->closefile(infile);
    if (cwd != NULL)
    {
      free(cwd);
      free(abs_filename);
    }
    return -1;
  }

  if (fsi->readchars(buf, 30, infile) != 30)
  {
    fsi->closefile(infile);
    if (cwd != NULL)
    {
      free(cwd);
      free(abs_filename);
    }
    return -1;
  }

  if (memcmp(buf, "FORM", 4) == 0)
  {
    // IFF file.

    if (
        (is_form_type(infile, "IFRS") != true)
        ||
        (find_chunk("ZCOD", infile) == -1)
       )
    {
      fsi->closefile(infile);
      if (cwd != NULL)
      {
        free(cwd);
        free(abs_filename);
      }
      return -1;
    }

    file_is_zblorb = true;

    if (find_chunk("IFmd", infile) == 0)
    {
      read_chunk_length(infile);
      chunk_length = get_last_chunk_length();
      file_babel = load_babel_info_from_blorb(
          infile, chunk_length, abs_filename, storyfile_timestamp);
      babel = file_babel;
    }

    find_chunk("ZCOD", infile);
    read_chunk_length(infile);
    length = get_last_chunk_length();

    if (fsi->readchars(buf, 30, infile) != 30)
    {
      fsi->closefile(infile);
      if (cwd != NULL)
      {
        free(cwd);
        free(abs_filename);
      }
      return -1;
    }
  }
  else
  {
    fsi->setfilepos(infile, 0, SEEK_END);
    length = fsi->getfilepos(infile);
    file_is_zblorb = false;
  }
  fsi->closefile(infile);

  val = (buf[16] << 24) | (buf[17] << 16) | (buf[18] << 8) | (buf[19]);
  if (
      ((val & 0xbe00f0f0) != 0x3030)
      ||
      (*buf < 1)
      ||
      (*buf > 8)
     )
  {
    if (cwd != NULL)
    {
      free(cwd);
      free(abs_filename);
    }
    return -2;
  }

  version = *buf;
  memcpy(serial, buf + 0x12, 6);
  serial[6] = '\0';
  checksum = (buf[0x1c] << 8) | buf[0x1d];
  release = (buf[2] << 8) | buf[3];

  if ((entry = get_z_story_entry(serial, release, length, story_list))
      != NULL)
  {
    // We already have the story in our story-list. If we have a raw file
    // we can just quit if the support-blorbfilename is the same (raw files
    // don't contain metadata which might have changed).
    if (
        (file_is_zblorb == false)
        &&
        (
         ( (entry->blorbfile == NULL) && (blorb_filename != NULL) )
         // ||  (Don't delete blorb file)
         // ( (blorb_filename == NULL) && (entry->blorbfile != NULL) )
         ||
         (
          (entry->blorbfile != NULL)
          &&
          (blorb_filename != NULL)
          &&
          (strcmp(blorb_filename, entry->blorbfile) == 0)
         )
        )
       )
    {
      if (cwd != NULL)
      {
        free(cwd);
        free(abs_filename);
      }
      return -3;
    }

    //printf("%ld / %ld\n", storyfile_timestamp, entry->storyfile_timestamp);

    // In case new file is a zblorb and we have save a raw file, remove the
    // raw and keep the blorb (so we can get images and sound). We'll also
    // re-read the file contents if the file has changed (metadata might
    // have been altered).
    if (
        (strcmp(entry->filetype, filetype_raw) == 0)
        ||
        (storyfile_timestamp > entry->storyfile_timestamp)
       )
    {
      remove_entry_from_list(story_list, entry);
      //printf("%s...\n", abs_filename);
    }
    else
    {
      if (cwd != NULL)
      {
        free(cwd);
        free(abs_filename);
      }
      return -4;
    }
  }

  ptr2 = NULL;

  if ((b_info = get_babel_story_info(
          release, serial, checksum, babel, file_is_zblorb)) != NULL)
  {
    title = (b_info->title == NULL ? empty_string : b_info->title);
    author = (b_info->author == NULL ? empty_string : b_info->author);
    language = (b_info->language == NULL ? empty_string : b_info->language);
    description
      = (b_info->description != NULL)
      ? b_info->description
      : empty_string;
  }
  else
  {
    if ((title = strrchr(abs_filename, '/')) == NULL)
      title = abs_filename;
    else
      title++;

    if ((ptr = strrchr(title, '.')) != NULL)
    {
      TRACE_LOG("strdup: %s\n", title);
      ptr2 = fizmo_strdup(title);
      ptr = strrchr(ptr2, '.');

      if ( ( (strlen(ptr) == 3) && (ptr[1] == 'z') && (isdigit(ptr[2]) != 0) )
          ||
          (strcasecmp(ptr, ".dat") == 0)
          ||
          (strcasecmp(ptr, ".zblorb") == 0)
         )
        *ptr = '\0';

      *ptr2 = toupper(*ptr2);

      title = ptr2;
    }

    author = empty_string;
    language = empty_string;
    description = empty_string;
  }

  add_entry_to_story_list(
      story_list,
      title,
      author,
      language,
      description,
      serial,
      version,
      length,
      checksum,
      release,
      abs_filename,
      file_is_zblorb ? NULL : blorb_filename,
      file_is_zblorb ? filetype_zblorb : filetype_raw,
      storyfile_timestamp);

  if (b_info != NULL)
    free_babel_story_info(b_info);

  if (ptr2 != NULL)
    free(ptr2);

  if (file_babel != NULL)
    free_babel_info(file_babel);

  if (cwd != NULL)
  {
    free(cwd);
    free(abs_filename);
  }

  return 0;
}
Exemplo n.º 2
0
static z_blorb_map *fizmo_blorb_init(z_file *blorb_file)
{
  z_blorb_map *result_wrapper;
  fizmo_blorb_map *result;
  fizmo_blorb *blorb;
  int resource_chunk_size;
  char buf[5];
  int nof_resources, nof_loops, blorb_index, resource_number;

  if (find_chunk("RIdx", blorb_file) == -1)
  {
    fsi->closefile(blorb_file);
    return NULL;
  }

  if (read_chunk_length(blorb_file) == -1)
    i18n_translate_and_exit(
        libfizmo_module_name,
        i18n_libfizmo_FUNCTION_CALL_P0S_RETURNED_ERROR_CODE_P1D,
        -0x0101,
        "read_chunk_length",
        errno);

  result = fizmo_malloc(sizeof(fizmo_blorb_map));
  result->blorb_file = blorb_file;
  result_wrapper = fizmo_malloc(sizeof(z_blorb_map));
  result_wrapper->blorb_map_implementation = result;

  resource_chunk_size = get_last_chunk_length();
  nof_resources = (resource_chunk_size - 4) / 12;

  // Skip next number of resources.
  if ((fsi->setfilepos(result->blorb_file, 4, SEEK_CUR)) != 0)
    i18n_translate_and_exit(
        libfizmo_module_name,
        i18n_libfizmo_FUNCTION_CALL_P0S_RETURNED_ERROR_CODE_P1D,
        -0x0101,
        "setfilepos",
        errno);

  TRACE_LOG("Number of resources in blorb file: %d.\n", nof_resources);

  // Count number of images and sounds.
  result->blorbs = fizmo_malloc(sizeof(fizmo_blorb*) * (nof_resources+1));

  buf[4] = '\0';
  blorb_index = 0;
  while (nof_resources > 0)
  {
    blorb = fizmo_malloc(sizeof(fizmo_blorb));

    if (fsi->readchars(buf, 4, result->blorb_file) != 4)
      i18n_translate_and_exit(
          libfizmo_module_name,
          i18n_libfizmo_FUNCTION_CALL_P0S_ABORTED_DUE_TO_ERROR,
          -0x0106,
          "readchars");

    TRACE_LOG("Type descriptor: %s\n", buf);
    if (strcmp(buf, "Pict") == 0)
      blorb->type = Z_BLORB_TYPE_PICT;
    else if (strcmp(buf, "Snd ") == 0)
      blorb->type = Z_BLORB_TYPE_SOUND;
    else if (strcmp(buf, "Exec") == 0)
      blorb->type = Z_BLORB_TYPE_EXEC;
    else
      // Unknown resource.
      i18n_translate_and_exit(
          libfizmo_module_name,
          i18n_libfizmo_UNKNOWN_ERROR_CASE,
          -1);

    blorb->resource_number = read_four_byte_number(result->blorb_file);
    blorb->offset = read_four_byte_number(result->blorb_file) + 8;
    blorb->v3_number_of_loops = -1;

    result->blorbs[blorb_index++] = blorb;

    nof_resources--;
  }

  result->blorbs[blorb_index] = NULL;

  if (find_chunk("Fspc", result->blorb_file) == 0)
  {
    if ((fsi->setfilepos(result->blorb_file, 4, SEEK_CUR)) != 0)
      i18n_translate_and_exit(
          libfizmo_module_name,
          i18n_libfizmo_FUNCTION_CALL_P0S_RETURNED_ERROR_CODE_P1D,
          -0x0101,
          "setfilepos",
          errno);

    result->frontispiece_image_no = read_four_byte_number(result->blorb_file);
  }
  else
    result->frontispiece_image_no = -1;

  if (ver < 5)
  {
    if (find_chunk("Loop", result->blorb_file) == 0)
    {
      nof_resources = read_four_byte_number(result->blorb_file) / 8;
      TRACE_LOG("Number of loop entries: %d.\n", nof_resources);

      while (nof_resources > 0)
      {
        resource_number = read_four_byte_number(result->blorb_file);
        nof_loops = read_four_byte_number(result->blorb_file);

        TRACE_LOG("Trying to find resource #%d.\n", resource_number);
        if ((blorb = fizmo_get_blorb(
                result_wrapper, Z_BLORB_TYPE_SOUND, resource_number)) != NULL)
        {
          TRACE_LOG("Resource found, setting nof_loops to %d.\n",
              nof_loops);
          blorb->v3_number_of_loops = nof_loops;
        }

        nof_resources--;
      }
    }
  }

  return result_wrapper;
}