Пример #1
0
void open_wav(char *wav)
  {
  TCHANINFO *inf;
  int i;
  struct t_wave *wavinf;
  FILE *snd;

  i=find_free_channel();
  if (i==-1) return;
  last_channel=i;
  inf=chaninfo+i;
  snd=fopen(wav,"rb");
  if (snd==NULL)
     {
     printf("Soubor %s neexistuje.\n",wav);
     return;
     }
  if (find_chunk(snd,WAV_FMT)==-1)
     {
     printf("Soubor %s ma poskozenou hlavicku\n",wav);
     fclose(snd);
     return;
     }
  wavinf=(struct t_wave *)malloc(get_chunk_size(snd));
  if (wavinf==NULL)
     {
     puts("Nedostatek pamˆti.");
     return;
     }
  read_chunk(snd,wavinf);
  if (wavinf->wav_mode!=1)
     {
     printf("Tento program podporuje pouze WAVy typu 1 (%s)\n",wav);
     free(wavinf);
     fclose(snd);
     return;
     }
  inf->chans=wavinf->chans;
  inf->bit8=wavinf->freq*wavinf->chans==wavinf->bps;
  inf->repstart=-1;
  inf->id=-1;
  inf->left.volume=32768;
  inf->right.volume=32768;
  inf->left.vls=0;
  inf->right.vls=0;
  free(wavinf);
  if (find_chunk(snd,WAV_DATA)==0)
     {
     printf("Soubor %s je poskozen\n",wav);
     fclose(snd);
     return;
     }
  inf->size=get_chunk_size(snd);
  fseek(snd,4,SEEK_CUR);
  inf->snd=snd;
  }
Пример #2
0
// binary search to find chunk for this instr
uint32_t find_chunk(uint64_t instr, uint32_t c1, uint32_t c2) {
    assert (c1 <= c2);
    if (c1 == c2) return c1;
    uint32_t mid = (c1 + c2) / 2;
    // if we ask for instr that is before every instr in log or after every one,
    // return first / last chunk
    if (instr < thePandalog->dir.instr[c1]) return c1;
    if (instr > thePandalog->dir.instr[c2]) return c2;
    if (thePandalog->dir.instr[c1] <= instr && instr <= thePandalog->dir.instr[mid]) {
        return find_chunk(instr, c1, mid);
    }
    assert (thePandalog->dir.instr[mid] <= instr && instr <= thePandalog->dir.instr[c2]);
    return find_chunk(instr, mid, c2);
}
Пример #3
0
void
wav_reader_c::parse_file() {
  int chunk_idx;

  if (m_in->read(&m_wheader.riff, sizeof(m_wheader.riff)) != sizeof(m_wheader.riff))
    throw mtx::input::header_parsing_x();

  scan_chunks();

  if ((chunk_idx = find_chunk("fmt ")) == -1)
    throw mtx::input::header_parsing_x();

  m_in->setFilePointer(m_chunks[chunk_idx].pos, seek_beginning);

  try {
    if (m_in->read(&m_wheader.format, sizeof(m_wheader.format)) != sizeof(m_wheader.format))
      throw false;

    if (static_cast<uint64_t>(m_chunks[chunk_idx].len) >= sizeof(alWAVEFORMATEXTENSIBLE)) {
      alWAVEFORMATEXTENSIBLE format;
      if (m_in->read(&format, sizeof(format)) != sizeof(format))
        throw false;
      memcpy(&m_wheader.common, &format, sizeof(m_wheader.common));

      m_format_tag = get_uint16_le(&m_wheader.common.wFormatTag);
      if (0xfffe == m_format_tag)
        m_format_tag = get_uint32_le(&format.extension.guid.data1);

    } else if (m_in->read(&m_wheader.common, sizeof(m_wheader.common)) != sizeof(m_wheader.common))
      throw false;

    else
      m_format_tag = get_uint16_le(&m_wheader.common.wFormatTag);

  } catch (...) {
    throw mtx::input::header_parsing_x();
  }

  if ((m_cur_data_chunk_idx = find_chunk("data", 0, false)) == -1)
    throw mtx::input::header_parsing_x();

  if (debugging_c::requested("wav_reader|wav_reader_headers"))
    dump_headers();

  m_in->setFilePointer(m_chunks[m_cur_data_chunk_idx].pos + sizeof(struct chunk_struct), seek_beginning);

  m_remaining_bytes_in_current_data_chunk = m_chunks[m_cur_data_chunk_idx].len;
}
Пример #4
0
void
chunk_registry::mark (void* ptr)
{
  auto header = find_chunk (ptr);
  assert (header && "Must be a valid ptr");
  header->set_mark (ptr);
}
Пример #5
0
bool
chunk_registry::is_marked (void* ptr)
{
  auto header = find_chunk (ptr);
  assert (header && "Must be a valid ptr");
  return header->is_marked (ptr);
}
Пример #6
0
void ensure_chunks(Chunk *chunks, int *chunk_count, int p, int q, int force) {
    int count = *chunk_count;
    for (int i = 0; i < count; i++) {
        Chunk *chunk = chunks + i;
        if (chunk_distance(chunk, p, q) >= DELETE_CHUNK_RADIUS) {
            map_free(&chunk->map);
            glDeleteBuffers(1, &chunk->position_buffer);
            glDeleteBuffers(1, &chunk->normal_buffer);
            glDeleteBuffers(1, &chunk->uv_buffer);
            Chunk *other = chunks + (--count);
            memcpy(chunk, other, sizeof(Chunk));
        }
    }
    int n = CREATE_CHUNK_RADIUS;
    for (int i = -n; i <= n; i++) {
        for (int j = -n; j <= n; j++) {
            int a = p + i;
            int b = q + j;
            if (!find_chunk(chunks, count, a, b)) {
                make_chunk(chunks + count, a, b);
                count++;
                if (!force) {
                    *chunk_count = count;
                    return;
                }
            }
        }
    }
    *chunk_count = count;
}
Пример #7
0
file_status_e
wav_reader_c::read(generic_packetizer_c *,
                   bool) {
  if (!m_demuxer)
    return FILE_STATUS_DONE;

  int64_t        requested_bytes = std::min(m_remaining_bytes_in_current_data_chunk, m_demuxer->get_preferred_input_size());
  unsigned char *buffer          = m_demuxer->get_buffer();
  int64_t        num_read;

  num_read = m_in->read(buffer, requested_bytes);

  if (0 >= num_read)
    return flush_packetizers();

  m_demuxer->process(num_read);

  m_remaining_bytes_in_current_data_chunk -= num_read;

  if (!m_remaining_bytes_in_current_data_chunk) {
    m_cur_data_chunk_idx = find_chunk("data", m_cur_data_chunk_idx + 1, false);

    if (-1 == m_cur_data_chunk_idx)
      return flush_packetizers();

    m_in->setFilePointer(m_chunks[m_cur_data_chunk_idx].pos + sizeof(struct chunk_struct), seek_beginning);

    m_remaining_bytes_in_current_data_chunk = m_chunks[m_cur_data_chunk_idx].len;
  }

  return FILE_STATUS_MOREDATA;
}
Пример #8
0
// another binary search to find first index into current chunk for this instr
uint32_t find_ind(uint64_t instr, uint32_t i1, uint32_t i2) {
    assert (i1 <= i2);
    if (i1 == i2) return i1;
    uint32_t mid = (i1 + i2) / 2;
    PandalogChunk *chunk = &(thePandalog->chunk);
    if (instr < chunk->entry[i1]->instr) {
        // just means first instr in log is after what we want
        return i1;
    }
    if (instr > chunk->entry[i2]->instr) {
        // just means we asked for instr that is after last instr in log
        return i2;
    }
    if (chunk->entry[i1]->instr <= instr && instr <= chunk->entry[mid]->instr) {
        return find_chunk(instr, i1, mid);
    }
    assert (chunk->entry[mid]->instr <= instr && instr <= chunk->entry[i2]->instr);
    return find_chunk(instr, mid, i2);
}
Пример #9
0
CStreamReader *CStreamReader::open_chunk	(const u32 &chunk_id)
{
	BOOL						compressed;
	u32							size = find_chunk(chunk_id,&compressed);
	if (!size)
		return					(0);

	R_ASSERT2					(!compressed,"cannot use CStreamReader on compressed chunks");
	CStreamReader				*result = xr_new<CStreamReader>();
	result->construct			(file_mapping_handle(),m_start_offset + tell(),size,m_archive_size,m_window_size);
	return						(result);
}
Пример #10
0
void _set_block(
    Chunk *chunks, int chunk_count,
    int p, int q, int x, int y, int z, int w)
{
    Chunk *chunk = find_chunk(chunks, chunk_count, p, q);
    if (chunk) {
        Map *map = &chunk->map;
        map_set(map, x, y, z, w);
        update_chunk(chunk);
    }
    db_insert_block(p, q, x, y, z, w);
}
Пример #11
0
int get_block(
    Chunk *chunks, int chunk_count,
    int x, int y, int z)
{
    int p = chunked(x);
    int q = chunked(z);
    Chunk *chunk = find_chunk(chunks, chunk_count, p, q);
    if (chunk) {
        Map *map = &chunk->map;
        return map_get(map, x, y, z);
    }
    return 0;
}
Пример #12
0
void _set_block(
    Chunk *chunks, int chunk_count,
    int p, int q, int x, int y, int z, int w)
{
    Chunk *chunk = find_chunk(chunks, chunk_count, p, q);
    if (chunk) {
        Map *map = &chunk->map;
        if (map_get(map, x, y, z) != w) {
            map_set(map, x, y, z, w);
            chunk->dirty = 1;
        }
    }
    db_insert_block(p, q, x, y, z, w);
}
Пример #13
0
void ensure_chunks(
    Chunk *chunks, int *chunk_count,
    float x, float y, float z, int force)
{
    int p = chunked(x);
    int q = chunked(z);
    int count = *chunk_count;
    for (int i = 0; i < count; i++) {
        Chunk *chunk = chunks + i;
        if (chunk_distance(chunk, p, q) >= DELETE_CHUNK_RADIUS) {
            map_free(&chunk->map);
            glDeleteBuffers(1, &chunk->position_buffer);
            glDeleteBuffers(1, &chunk->normal_buffer);
            glDeleteBuffers(1, &chunk->uv_buffer);
            Chunk *other = chunks + (--count);
            memcpy(chunk, other, sizeof(Chunk));
        }
    }
    int rings = force ? 1 : CREATE_CHUNK_RADIUS;
    int generated = 0;
    for (int ring = 0; ring <= rings; ring++) {
        for (int dp = -ring; dp <= ring; dp++) {
            for (int dq = -ring; dq <= ring; dq++) {
                if (ring != MAX(ABS(dp), ABS(dq))) {
                    continue;
                }
                if (!force && generated && ring > 1) {
                    continue;
                }
                int a = p + dp;
                int b = q + dq;
                Chunk *chunk = find_chunk(chunks, count, a, b);
                if (chunk) {
                    if (chunk->dirty) {
                        gen_chunk_buffers(chunk);
                        generated++;
                    }
                }
                else {
                    if (count < MAX_CHUNKS) {
                        create_chunk(chunks + count, a, b);
                        generated++;
                        count++;
                    }
                }
            }
        }
    }
    *chunk_count = count;
}
Пример #14
0
Файл: FS.cpp Проект: 2asoft/xray
//---------------------------------------------------
// base stream
IReader*	IReader::open_chunk(u32 ID)
{
	BOOL	bCompressed;

	u32	dwSize = find_chunk(ID,&bCompressed);
	if (dwSize!=0) {
		if (bCompressed) {
			BYTE*		dest;
			unsigned	dest_sz;
			_decompressLZ(&dest,&dest_sz,pointer(),dwSize);
			return new CTempReader(dest,		dest_sz,		tell()+dwSize);
		} else {
			return new IReader(pointer(),	dwSize,			tell()+dwSize);
		}
	} else return 0;
};
Пример #15
0
model decode_omdl(const path_t& path
	, const void* buffer, size_t size
	, const layout_t& desired_layout
	, const allocator& subsets_alloc
	, const allocator& mesh_alloc
	, const allocator& temp_alloc)
{
	if (!is_omdl(buffer, size))
		return model();

	auto hdr = (const file_header*)buffer;
	auto chk = hdr->find_chunk(omdl_info_signature);

	if (!chk)
		oThrow(std::errc::invalid_argument, "invalid omdl: no info section");

	auto info = *chk->data<info_t>();
	
	model mdl(info, subsets_alloc, mesh_alloc);

	chk = chk->next();
	
	if (chk->fourcc != omdl_subsets_signature)
		oThrow(std::errc::invalid_argument, "invalid omdl: no subsets section");

	memcpy(mdl.subsets(), chk->data<subset_t>(), chk->uncompressed_bytes);

	chk = chk->next();

	if (chk->fourcc != omdl_indices_signature)
		oThrow(std::errc::invalid_argument, "invalid omdl: no indices section");

	memcpy(mdl.indices(), chk->data<uint16_t>(), chk->uncompressed_bytes);

	const uint32_t nslots = info.num_slots;
	for (uint32_t slot = 0; slot < nslots; slot++)
	{
		chk = chk->next();

		if (chk->fourcc != omdl_vertex_slot_signature)
			oThrow(std::errc::invalid_argument, "invalid omdl: no vertices slot section");

		memcpy(mdl.vertices(slot), chk->data<void>(), chk->uncompressed_bytes);
	}

	return mdl;
}
Пример #16
0
int highest_block(Chunk *chunks, int chunk_count, float x, float z) {
    int result = -1;
    int nx = roundf(x);
    int nz = roundf(z);
    int p = floorf(roundf(x) / CHUNK_SIZE);
    int q = floorf(roundf(z) / CHUNK_SIZE);
    Chunk *chunk = find_chunk(chunks, chunk_count, p, q);
    if (chunk) {
        Map *map = &chunk->map;
        MAP_FOR_EACH(map, e) {
            if (is_obstacle(e->w) && e->x == nx && e->z == nz) {
                result = MAX(result, e->y);
            }
        } END_MAP_FOR_EACH;
    }
    return result;
}
Пример #17
0
int collide(
    Chunk *chunks, int chunk_count,
    int height, float *x, float *y, float *z)
{
    int result = 0;
    int p = floorf(roundf(*x) / CHUNK_SIZE);
    int q = floorf(roundf(*z) / CHUNK_SIZE);
    Chunk *chunk = find_chunk(chunks, chunk_count, p, q);
    if (!chunk) {
        return result;
    }
    Map *map = &chunk->map;
    int nx = roundf(*x);
    int ny = roundf(*y);
    int nz = roundf(*z);
    float px = *x - nx;
    float py = *y - ny;
    float pz = *z - nz;
    float pad = 0.25;
    for (int dy = 0; dy < height; dy++) {
        if (px < -pad && is_obstacle(map_get(map, nx - 1, ny - dy, nz))) {
            *x = nx - pad;
        }
        if (px > pad && is_obstacle(map_get(map, nx + 1, ny - dy, nz))) {
            *x = nx + pad;
        }
        if (py < -pad && is_obstacle(map_get(map, nx, ny - dy - 1, nz))) {
            *y = ny - pad;
            result = 1;
        }
        if (py > pad && is_obstacle(map_get(map, nx, ny - dy + 1, nz))) {
            *y = ny + pad;
            result = 1;
        }
        if (pz < -pad && is_obstacle(map_get(map, nx, ny - dy, nz - 1))) {
            *z = nz - pad;
        }
        if (pz > pad && is_obstacle(map_get(map, nx, ny - dy, nz + 1))) {
            *z = nz + pad;
        }
    }
    return result;
}
Пример #18
0
void *malloc(size_t size)
{

  if (size == 0 )
   return NULL;
  size_t lenght = word_align(size);
  struct chunk *c = find_chunk(size);

  if(c->next==NULL)
   {
    if (extend_heap(c,lenght) == 0)
     return NULL;
   }
  else
   {
    c->next->free = 0;
   }
  return (&c->next->data);

}
Пример #19
0
void pandalog_seek(uint64_t instr) {
    assert(in_read_mode());
    // figure out which chunk this instr in is
    uint32_t c = find_chunk(instr, 0, thePandalog->dir.max_chunks-1);
    thePandalog->chunk_num = c;
    unmarshall_chunk(c);
    // figure out ind
    uint32_t ind = find_ind(instr, 0, thePandalog->dir.num_entries[c]-1);
    if (thePandalog->mode == PL_MODE_READ_BWD) {
        // need *last* entry with that instr for backward mode
        uint32_t i;
        //        uint8_t found_entry = 0;
        for (i=ind; i<thePandalog->dir.num_entries[c]; i++) {
            Panda__LogEntry *ple = thePandalog->chunk.entry[i];
            if (ple->instr != instr || instr > ple->instr) {
                ind --;
                break;
            }
        }
    }
    thePandalog->chunk.ind_entry = ind;
}
Пример #20
0
void ensure_chunks(Chunk *chunks, int *chunk_count, int p, int q, int force) {
    int count = *chunk_count;
    for (int i = 0; i < count; i++) {
        Chunk *chunk = chunks + i;
        if (chunk_distance(chunk, p, q) >= DELETE_CHUNK_RADIUS) {
            map_free(&chunk->map);
            glDeleteBuffers(1, &chunk->position_buffer);
            glDeleteBuffers(1, &chunk->normal_buffer);
            glDeleteBuffers(1, &chunk->uv_buffer);
            Chunk *other = chunks + (--count);
            memcpy(chunk, other, sizeof(Chunk));
        }
    }
    int n = force ? 1 : CREATE_CHUNK_RADIUS;
    for (int i = 0; i <= n; i++) {
        for (int dp = -n; dp <= n; dp++) {
            for (int dq = -n; dq <= n; dq++) {
                int j = MAX(ABS(dp), ABS(dq));
                if (i != j) {
                    continue;
                }
                int a = p + dp;
                int b = q + dq;
                if (!find_chunk(chunks, count, a, b)) {
                    make_chunk(chunks + count, a, b);
                    count++;
                    if (!force) {
                        *chunk_count = count;
                        return;
                    }
                }
            }
        }
    }
    *chunk_count = count;
}
Пример #21
0
void mix_buffer(int size)
  {
  int chan,i;
  memset(source,0,size*2);
  for(chan=0;chan<CHANNELS;chan++)
     {
     if (chaninfo[chan].snd!=NULL)
        {
        TCHANINFO *inf=chaninfo+chan;

        for(i=0;i<size;i+=2)
           {
           int left,right;
           if (inf->bit8)
              {
              fread(&left,1,1,inf->snd);left=(short)(left*256);
              left^=0xffff8000;
              inf->size--;
              }
           else
              {
              fread(&left,1,2,inf->snd);left=(short)left;
              inf->size-=2;
              }
           if (inf->chans==1) right=left;
           else
              if (inf->bit8)
                 {
                 fread(&right,1,1,inf->snd);right=(short)(right*256);
                 right^=0xffff8000;
                 inf->size--;
                 }
              else
                 {
                 fread(&right,1,2,inf->snd);right=(short)right;
                 inf->size-=2;
                 }
           left=(int)left*inf->left.volume/(32768);
           right=(int)right*inf->right.volume/(32768);
           left=left*glob_volume/256;
           right=right*glob_volume/256;
           calc_vls(&inf->left);
           calc_vls(&inf->right);
           left+=source[i];
           right+=source[i+1];
           if (left>32767) left=32767;
           if (left<-32767) left=-32767;
           if (right>32767) right=32767;
           if (right<-32767) right=-32767;
           source[i]=left;
           source[i+1]=right;
           if (inf->size<=0)
              {
              if (inf->repstart!=-1)
                 {
                 fseek(inf->snd,0,SEEK_SET);
                 find_chunk(inf->snd,WAV_DATA);
                 inf->size=get_chunk_size(inf->snd);
                 fseek(inf->snd,4,SEEK_CUR);
                 fseek(inf->snd,inf->repstart,SEEK_CUR);
                 inf->size-=inf->repstart;
                 }
              else
                 {
                 fclose(inf->snd);
                 inf->snd=NULL;
                 break;
                 }
              }
           }
        }
     }
  }
Пример #22
0
/** Prepares "start" RDA packet with channel names determined from the corresponding chunk (or empty)
	Also converts to little-endian if this machine is big endian
	@param hdr  Points to headerdef_t structure, will be filled, may not be NULL
	@return created start item, or NULL on error (connection / out of memory)
*/
rda_buffer_item_t *rda_aux_get_hdr_prep_start(int ft_buffer, headerdef_t *hdr) {
	rda_buffer_item_t *item = NULL;
	const ft_chunk_t *chunk;
	rda_msg_start_t *R;
	char *str;
	double *dRes;
	const void *dResSource;
	size_t bytesTotal;
	int i,r,numExtraZeros,sizeOrgNames;
	message_t req, *resp = NULL;
	messagedef_t msg_def;	
	
	req.def = &msg_def;
	req.buf = NULL;
	msg_def.version = VERSION;
	msg_def.command = GET_HDR;
	msg_def.bufsize = 0;
	
	r = clientrequest(ft_buffer, &req, &resp);
	if (r<0 || resp == NULL || resp->def == NULL) {
		goto cleanup;
	}
	
	if (resp->def->command != GET_OK || resp->def->bufsize < sizeof(headerdef_t) || resp->buf == NULL) {
		goto cleanup;
	}
	
	memcpy(hdr, resp->buf, sizeof(headerdef_t));
	
	/* Ok, we have the basic header, now look for proper FT_CHUNK_RESOLUTIONS */
	chunk = find_chunk(resp->buf, sizeof(headerdef_t), resp->def->bufsize, FT_CHUNK_RESOLUTIONS);
	if (chunk != NULL && chunk->def.size == hdr->nchans*sizeof(double)) {
		dResSource = chunk->data;
		/* fine - we just need a memcpy later on */
	} else {
		dResSource = NULL;
		/* no suitable chunk found - set defaults later on */
	}
	
	/* Now see if we can find channel names */
	chunk = find_chunk(resp->buf, sizeof(headerdef_t), resp->def->bufsize, FT_CHUNK_CHANNEL_NAMES);
	if (chunk != NULL && chunk->def.size >= hdr->nchans) {
		/* The chunk seems ok - check whether we really have N (0-terminated) strings */
		int k,nz = 0;
		for (k = 0; k<chunk->def.size && nz<=hdr->nchans; k++) {
			if (chunk->data[k] == 0) nz++;
		}
		/* Okay, either k is at the end and we have nz<=N, or we have reached N=nz before the
		   end of the chunk. In both cases, it's safe to transmit the first 'k' bytes and
		   add (N-nz) trailing zeros */
		numExtraZeros = hdr->nchans - nz;
		sizeOrgNames = k;
	} else {
		sizeOrgNames = 0;
		numExtraZeros = hdr->nchans;
	}
	
	bytesTotal = sizeof(rda_msg_start_t) + hdr->nchans*(sizeof(double)) + sizeOrgNames + numExtraZeros;
		
	item = rda_aux_alloc_item(bytesTotal);
	if (item == NULL) goto cleanup;
		
	R = (rda_msg_start_t *) item->data;
	memcpy(R->hdr.guid, _rda_guid, sizeof(_rda_guid));
	R->hdr.nSize = bytesTotal;
	R->hdr.nType = RDA_START_MSG;
	R->nChannels = hdr->nchans;
	R->dSamplingInterval = 1.0e6/(double) hdr->fsample;	/* should be in microseconds */
	
	if (_i_am_big_endian_) {
		/* take care of hdr.nSize, hdr.nType, nChannels */
		ft_swap32(3, &(R->hdr.nSize)); 
		ft_swap64(1, &(R->dSamplingInterval));
	}
	
	/* R+1 points to first byte after header info */
	dRes = (double *) ((void *)(R+1)); 
	if (dResSource == NULL) {
		/* Fill with resolution = 1.0 -- we have nothing better */
		for (i=0;i<hdr->nchans;i++) dRes[i]=1.0;
	} else {
		memcpy(dRes, dResSource, hdr->nchans * sizeof(double));
	}
	/* swap byte order if necessary */
	if (_i_am_big_endian_) {
		ft_swap64(hdr->nchans, dRes);
	}
	
	/* Let 'str' point to first byte after the resolution values */
	str = (char *) ((void *)(dRes + hdr->nchans));
	if (sizeOrgNames > 0) {
		memcpy(str, chunk->data, sizeOrgNames);
	}
	for (i=0;i<numExtraZeros;i++) str[sizeOrgNames + i] = 0;
	
	/* done */
cleanup:
	if (resp) {
		if (resp->def) free(resp->def);
		if (resp->buf) free(resp->buf);
		free(resp);
	}
	return item;
}	
Пример #23
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;
}
// Besides passing in type, also pass some necessary fields as parameters
// Other fields in the parameters can be arbitrary values
// To make a WHOHAS packet, pass in the request and *packet_count
// To make a IHAVE packet, pass in a WHOHAS packet as packet_in
// To make a Get packet, pass in p_chunk
// 
struct packet* make_packet(unsigned char packet_type, struct Chunk* p_chunk, char* data, int data_size, int seq_number, int ack_number, struct packet* packet_in, int* packet_count, struct Request* request){
  unsigned char i = 0;
  int j = 0;
  int unfinished_chunk_count = 0;
  struct packet* packet = NULL;
  switch(packet_type){
    case WHOHAS:
      for(i=0;i<request->chunk_number;i++){
        // TODO: here may need to change add more state to chunks
        if(request->chunks[i].state == NOT_STARTED){
          unfinished_chunk_count++;
        }
      }
      if(unfinished_chunk_count%CHUNK_PER_PACKET==0){
        *packet_count = unfinished_chunk_count/CHUNK_PER_PACKET;
      }
      else{
        *packet_count = unfinished_chunk_count/CHUNK_PER_PACKET + 1; 
      }
      struct packet* packets = (struct packet*)malloc(sizeof(struct packet)* (*packet_count));
      memset(packets, 0, sizeof(struct packet)* (*packet_count));
      if(unfinished_chunk_count==0){
        free_packets(packets, *packet_count);
        packets = NULL;
      }
      int current_chunk_index = 0;
      for(j=0;j<(*packet_count);j++){
        unsigned char chunk_count = CHUNK_PER_PACKET;
        if(*packet_count <= j+1){
          chunk_count = (unsigned char)(unfinished_chunk_count - j*CHUNK_PER_PACKET);
        }
        fill_header(&packets[j].header, WHOHAS, chunk_count*SHA1_HASH_SIZE+HEADER_LENGTH+CHUNK_NUMBER_AND_PADDING_SIZE, 0, 0);
        *(packets[j].payload) = chunk_count;
        int k=0;
        for(k=0;k<chunk_count;k++){
          for(; current_chunk_index<request->chunk_number;current_chunk_index++){
            if(request->chunks[current_chunk_index].state==NOT_STARTED){
              memcpy(packets[j].payload+CHUNK_NUMBER_AND_PADDING_SIZE+k*SHA1_HASH_SIZE,(request->chunks)[current_chunk_index].hash, SHA1_HASH_SIZE);
              current_chunk_index++;
              break;
            } 
          }
        }
      }
      return packets;
    case IHAVE:
      packet = (struct packet*)malloc(sizeof(struct packet));
      memset(packet, 0, sizeof(struct packet));
      unsigned char chunk_count = *((char*)packet_in+16);
      unsigned char count_ihave = 0;

      for(i=0;i<chunk_count;i++){
        uint8_t* hash = (uint8_t*)((char*)packet_in+16+CHUNK_NUMBER_AND_PADDING_SIZE+i*SHA1_HASH_SIZE);
        if(find_chunk(hash)>0){
          memcpy(packet->payload+CHUNK_NUMBER_AND_PADDING_SIZE+count_ihave*SHA1_HASH_SIZE, hash, SHA1_HASH_SIZE);
          count_ihave++;
        }
      }
      if(count_ihave==0){
        free_packet(packet);
        packet = NULL;
      }
      else{
        fill_header(&(packet->header), IHAVE, count_ihave*SHA1_HASH_SIZE+HEADER_LENGTH+CHUNK_NUMBER_AND_PADDING_SIZE, 0, 0);
        // *(packet->payload) = count_ihave;
        memcpy(packet->payload, &count_ihave, 1);
      }
      break;
    case GET:
      packet = (struct packet*)malloc(sizeof(struct packet));
      memset(packet, 0, sizeof(struct packet));
      fill_header(&packet->header, GET, SHA1_HASH_SIZE+HEADER_LENGTH, 0, 0);
      memcpy(packet->payload, p_chunk->hash, SHA1_HASH_SIZE);
      break;
    case DATA:
      packet = (struct packet*)malloc(sizeof(struct packet));
      memset(packet, 0, sizeof(struct packet));
      fill_header(&packet->header, DATA, data_size+HEADER_LENGTH, seq_number, 0);
      memcpy(packet->payload, data, data_size);
      break;
    case ACK:
      packet = (struct packet*)malloc(sizeof(struct packet));
      memset(packet, 0, sizeof(struct packet));
      fill_header(&packet->header, ACK, HEADER_LENGTH, 0, ack_number);
      break;
    default:
      printf("Should not happen in make_packet\n");
      break;
  }
  return packet;
}
Пример #25
0
bool loadWavSampleFromBytes(const float *inData, int len, QuickVec<unsigned char> &outBuffer, int *channels, int *bitsPerSample, int* outSampleRate)
{
    const char* start = (const char*)inData;
    const char* end = start + len;
    const char* ptr = start;
    WAVE_Format wave_format;
    RIFF_Header riff_header;
    WAVE_Data wave_data;
    unsigned char* data;

    // Read in the first chunk into the struct
    memcpy(&riff_header, ptr, sizeof(RIFF_Header));
    ptr += sizeof(RIFF_Header);

    //check for RIFF and WAVE tag in memeory
    if ((riff_header.chunkID[0] != 'R'  ||
            riff_header.chunkID[1] != 'I'  ||
            riff_header.chunkID[2] != 'F'  ||
            riff_header.chunkID[3] != 'F') ||
            (riff_header.format[0] != 'W'  ||
             riff_header.format[1] != 'A'  ||
             riff_header.format[2] != 'V'  ||
             riff_header.format[3] != 'E'))
    {
        LOG_SOUND("Invalid RIFF or WAVE Header!\n");
        return false;
    }

    //Read in the 2nd chunk for the wave info
    ptr = find_chunk(ptr, end, "fmt ");
    if (!ptr) {
        return false;
    }
    readStruct(wave_format, ptr);

    //check for fmt tag in memory
    if (wave_format.subChunkID[0] != 'f' ||
            wave_format.subChunkID[1] != 'm' ||
            wave_format.subChunkID[2] != 't' ||
            wave_format.subChunkID[3] != ' ')
    {
        LOG_SOUND("Invalid Wave Format!\n");
        return false;
    }

    ptr = find_chunk(ptr, end, "data");
    if (!ptr) {
        return false;
    }

    const char* base = readStruct(wave_data, ptr);

    //check for data tag in memory
    if (wave_data.subChunkID[0] != 'd' ||
            wave_data.subChunkID[1] != 'a' ||
            wave_data.subChunkID[2] != 't' ||
            wave_data.subChunkID[3] != 'a')
    {
        LOG_SOUND("Invalid Wav Data Header!\n");
        return false;
    }

    //Allocate memory for data
    //data = new unsigned char[wave_data.subChunk2Size];

    // Read in the sound data into the soundData variable
    size_t size = wave_data.subChunkSize;
    if (size > (end - base)) {
        return false;
    }

    /*mlChannels = wave_format.numChannels;
    if (mlChannels == 2)
    {
    	if (wave_format.bitsPerSample == 8)
    	{
    		mFormat = AL_FORMAT_STEREO8;
    		mlSamples = size / 2;
    	}
    	else //if (wave_format.bitsPerSample == 16)
    	{
    		mlSamples = size / 4;
    		mFormat = AL_FORMAT_STEREO16;
    	}
    } else //if (mlChannels == 1)
    {
    	if (wave_format.bitsPerSample == 8)
    	{
    		mlSamples = size;
    		mFormat = AL_FORMAT_MONO8;
    	}
    	else //if (wave_format.bitsPerSample == 16)
    	{
    		mlSamples = size / 2;
    		mFormat = AL_FORMAT_MONO16;
    	}
    }
    mlFrequency = wave_format.sampleRate;
    mfTotalTime = float(mlSamples) / float(mlFrequency);*/

    //Store in the outbuffer
    outBuffer.Set((unsigned char*)base, size);

    //Now we set the variables that we passed in with the
    //data from the structs
    *outSampleRate = (int)wave_format.sampleRate;

    //The format is worked out by looking at the number of
    //channels and the bits per sample.
    *channels = wave_format.numChannels;
    *bitsPerSample = wave_format.bitsPerSample;

    //clean up and return true if successful
    //fclose(f);
    //delete[] data;

    return true;
}
Пример #26
0
Файл: WAV.cpp Проект: vroad/lime
	bool WAV::Decode (Resource *resource, AudioBuffer *audioBuffer) {
		
		WAVE_Format wave_format;
		RIFF_Header riff_header;
		WAVE_Data wave_data;
		unsigned char* data;
		
		FILE_HANDLE *file = NULL;
		
		if (resource->path) {
			
			file = lime::fopen (resource->path, "rb");
			
			if (!file) {
				
				return false;
				
			}
			
			int result = lime::fread (&riff_header, sizeof (RIFF_Header), 1, file);
			
			if ((riff_header.chunkID[0] != 'R' || riff_header.chunkID[1] != 'I' || riff_header.chunkID[2] != 'F' || riff_header.chunkID[3] != 'F') || (riff_header.format[0] != 'W' || riff_header.format[1] != 'A' || riff_header.format[2] != 'V' || riff_header.format[3] != 'E')) {
				
				lime::fclose (file);
				return false;
				
			}
			
			long int currentHead = 0;
			bool foundFormat = false;
			
			while (!foundFormat) {
				
				currentHead = lime::ftell (file);
				result = lime::fread (&wave_format, sizeof (WAVE_Format), 1, file);
				
				if (result != 1) {
					
					LOG_SOUND ("Invalid Wave Format!\n");
					lime::fclose (file);
					return false;
					
				}
				
				if (wave_format.subChunkID[0] != 'f' || wave_format.subChunkID[1] != 'm' || wave_format.subChunkID[2] != 't' || wave_format.subChunkID[3] != ' ') {
					
					lime::fseek (file, wave_format.subChunkSize, SEEK_CUR);
					
				} else {
					
					foundFormat = true;
					
				}
				
			}
			
			bool foundData = false;
			
			while (!foundData) {
				
				currentHead = lime::ftell (file);
				result = lime::fread (&wave_data, sizeof (WAVE_Data), 1, file);
				
				if (result != 1) {
					
					LOG_SOUND ("Invalid Wav Data Header!\n");
					lime::fclose (file);
					return false;
					
				}
				
				if (wave_data.subChunkID[0] != 'd' || wave_data.subChunkID[1] != 'a' || wave_data.subChunkID[2] != 't' || wave_data.subChunkID[3] != 'a') {
					
					lime::fseek (file, currentHead + sizeof (WAVE_Data) + wave_data.subChunkSize, SEEK_SET);
					
				} else {
					
					foundData = true;
					
				}
				
			}
			
			audioBuffer->data = new Bytes (wave_data.subChunkSize);
			audioBuffer->length = wave_data.subChunkSize;
			
			if (!lime::fread (audioBuffer->data->Data (), wave_data.subChunkSize, 1, file)) {
				
				LOG_SOUND ("error loading WAVE data into struct!\n");
				lime::fclose (file);
				return false;
				
			}
			
			lime::fclose (file);
			
		} else {
			
			const char* start = (const char*)resource->data->Data ();
			const char* end = start + resource->data->Length ();
			const char* ptr = start;
			
			memcpy (&riff_header, ptr, sizeof (RIFF_Header));
			ptr += sizeof (RIFF_Header);
			
			if ((riff_header.chunkID[0] != 'R' || riff_header.chunkID[1] != 'I' || riff_header.chunkID[2] != 'F' || riff_header.chunkID[3] != 'F') || (riff_header.format[0] != 'W' || riff_header.format[1] != 'A' || riff_header.format[2] != 'V' || riff_header.format[3] != 'E')) {
				
				return false;
				
			}
			
			ptr = find_chunk (ptr, end, "fmt ");
			
			if (!ptr) {
				
				return false;
				
			}
			
			readStruct (wave_format, ptr);
			
			if (wave_format.subChunkID[0] != 'f' || wave_format.subChunkID[1] != 'm' || wave_format.subChunkID[2] != 't' || wave_format.subChunkID[3] != ' ') {
				
				LOG_SOUND ("Invalid Wave Format!\n");
				return false;
				
			}
			
			ptr = find_chunk (ptr, end, "data");
			
			if (!ptr) {
				
				return false;
				
			}
			
			const char* base = readStruct (wave_data, ptr);
			
			if (wave_data.subChunkID[0] != 'd' || wave_data.subChunkID[1] != 'a' || wave_data.subChunkID[2] != 't' || wave_data.subChunkID[3] != 'a') {
				
				LOG_SOUND ("Invalid Wav Data Header!\n");
				return false;
				
			}
			
			audioBuffer->data->Resize (wave_data.subChunkSize);
			
			size_t size = wave_data.subChunkSize;
			
			if (size > (end - base)) {
				
				return false;
				
			}
			
			unsigned char* bytes = audioBuffer->data->Data ();
			memcpy (bytes, base, size);
			
		}
		
		audioBuffer->sampleRate = (int)wave_format.sampleRate;
		audioBuffer->channels = wave_format.numChannels;
		audioBuffer->bitsPerSample = wave_format.bitsPerSample;
		
		return true;
		
	}
Пример #27
0
int load_pic(char *name)
{
    FILE *fd = fopen(name, "rb");
    Uint32 type;

    /* Couldn't open */
    if (!fd) return 0;

    type = read_header(fd);

    /* Not an IFF file */
    if (!type)
    {
        fclose(fd);
        return 0;
    }

    switch(type)
    {
    case PBM:
    {
        if (find_chunk(fd, BMHD))
        {
            Uint16 sizex = freadhe16(fd);
            Uint16 sizey = freadhe16(fd);
            Uint8 compression;
            int colors = 256;
            Uint32 bodylength;

            /*
             * Hop over the "hotspot", planes & masking (stencil pictures are
             * always saved as ILBMs!
             */
            fseek(fd, 6, SEEK_CUR);
            compression = fread8(fd);
            fread8(fd);
            fread8(fd);
            fread8(fd);
            /*
             * That was all we needed of the BMHD, now the CMAP (optional hehe!)
             */
            if (find_chunk(fd, CMAP))
            {
                int count;
                for (count = 0; count < colors; count++)
                {
                    sc.red[count] = fread8(fd) >> 2;
                    sc.green[count] = fread8(fd) >> 2;
                    sc.blue[count] = fread8(fd) >> 2;
                }
            }
            /*
             * Now the BODY chunk, this is important!
             */
            bodylength = find_chunk(fd, BODY);

            if (bodylength)
            {
                sc.sizex = sizex;
                sc.sizey = sizey;
                sc.data = malloc(sc.sizex * sc.sizey);
                if (!sc.data)
                {
                    fclose(fd);
                    return 0;
                }
                if (!compression)
                {
                    int ycount;
                    for (ycount = 0; ycount < sizey; ycount++)
                    {
                        fread(&sc.data[sc.sizex * ycount], sizex, 1, fd);
                    }
                }
                else
                {
                    int ycount;

                    char *ptr = malloc(bodylength);
                    char *origptr = ptr;
                    if (!ptr)
                    {
                        fclose(fd);
                        return 0;
                    }

                    fread(ptr, bodylength, 1, fd);

                    /* Run-length encoding */
                    for (ycount = 0; ycount < sizey; ycount++)
                    {
                        int total = 0;
                        while (total < sizex)
                        {
                            signed char decision = *ptr++;
                            if (decision >= 0)
                            {
                                memcpy(&sc.data[sc.sizex * ycount + total], ptr, decision + 1);
                                ptr += decision + 1;
                                total += decision + 1;
                            }
                            if ((decision < 0) && (decision != -128))
                            {
                                memset(&sc.data[sc.sizex * ycount + total], *ptr++, -decision + 1);
                                total += -decision + 1;
                            }
                        }
                    }
                    free(origptr);
                }
            }
        }
    }
    break;

    case ILBM:
    {
        if (find_chunk(fd, BMHD))
        {
            Uint16 sizex = freadhe16(fd);
            Uint16 sizey = freadhe16(fd);
            Uint8 compression;
            Uint8 planes;
            Uint8 mask;
            int colors;
            Uint32 bodylength;

            /*
             * Hop over the "hotspot"
             */
            fseek(fd, 4, SEEK_CUR);
            planes = fread8(fd);
            mask = fread8(fd);
            compression = fread8(fd);
            fread8(fd);
            fread8(fd);
            fread8(fd);
            colors = poweroftwo[planes];
            if (mask > 1) mask = 0;
            /*
             * That was all we needed of the BMHD, now the CMAP (optional hehe!)
             */
            if (find_chunk(fd, CMAP))
            {
                int count;
                for (count = 0; count < 256; count++)
                {
                    sc.red[count] = 0;
                    sc.green[count] = 0;
                    sc.blue[count] = 0;
                }
                sc.red[255] = 255;
                sc.green[255] = 255;
                sc.blue[255] = 255;
                for (count = 0; count < colors; count++)
                {
                    sc.red[count] = fread8(fd) >> 2;
                    sc.green[count] = fread8(fd) >> 2;
                    sc.blue[count] = fread8(fd) >> 2;
                }
            }
            /*
             * Now the BODY chunk, this is important!
             */
            bodylength = find_chunk(fd, BODY);

            if (bodylength)
            {
                char *ptr;
                char *origptr;
                char *unpackedptr;
                char *workptr;
                int ycount, plane;
                int bytes, dbytes;

                sc.sizex = sizex;
                sc.sizey = sizey;
                sc.data = malloc(sc.sizex * sc.sizey);
                memset(sc.data, 0, sc.sizex * sc.sizey);
                if (!sc.data)
                {
                    fclose(fd);
                    return 0;
                }
                origptr = malloc(bodylength * 2);
                ptr = origptr;
                if (!origptr)
                {
                    fclose(fd);
                    return 0;
                }
                fread(origptr, bodylength, 1, fd);
                if (compression)
                {
                    dbytes = sizey * (planes + mask) * ((sizex + 7) / 8);
                    unpackedptr = malloc(dbytes);
                    workptr = unpackedptr;
                    if (!unpackedptr)
                    {
                        fclose(fd);
                        return 0;
                    }
                    bytes = 0;
                    while (bytes < dbytes)
                    {
                        signed char decision = *ptr++;
                        if (decision >= 0)
                        {
                            memcpy(workptr, ptr, decision + 1);
                            workptr += decision + 1;
                            ptr += decision + 1;
                            bytes += decision + 1;
                        }
                        if ((decision < 0) && (decision != -128))
                        {
                            memset(workptr, *ptr++, -decision + 1);
                            workptr += -decision + 1;
                            bytes += -decision + 1;
                        }
                    }
                    free(origptr);
                    origptr = unpackedptr;
                    ptr = unpackedptr;
                }
                for (ycount = 0; ycount < sizey; ycount++)
                {
                    for (plane = 0; plane < planes; plane++)
                    {
                        int xcount = (sizex + 7) / 8;
                        int xcoord = 0;
                        while (xcount)
                        {
                            if (*ptr & 128) sc.data[sc.sizex * ycount + xcoord + 0] |= poweroftwo[plane];
                            if (*ptr & 64 ) sc.data[sc.sizex * ycount + xcoord + 1] |= poweroftwo[plane];
                            if (*ptr & 32 ) sc.data[sc.sizex * ycount + xcoord + 2] |= poweroftwo[plane];
                            if (*ptr & 16 ) sc.data[sc.sizex * ycount + xcoord + 3] |= poweroftwo[plane];
                            if (*ptr & 8  ) sc.data[sc.sizex * ycount + xcoord + 4] |= poweroftwo[plane];
                            if (*ptr & 4  ) sc.data[sc.sizex * ycount + xcoord + 5] |= poweroftwo[plane];
                            if (*ptr & 2  ) sc.data[sc.sizex * ycount + xcoord + 6] |= poweroftwo[plane];
                            if (*ptr & 1  ) sc.data[sc.sizex * ycount + xcoord + 7] |= poweroftwo[plane];
                            ptr++;
                            xcoord += 8;
                            xcount--;
                        }
                    }
                    if (mask)
                    {
                        ptr += (sizex + 7) / 8;
                    }
                }
                free(origptr);
            }
        }
    }
    break;
    }
    fclose(fd);
    return 1;
}
Пример #28
0
int find_chunk_le(STREAMFILE *streamFile, uint32_t chunk_id, off_t start_offset, int full_chunk_size, off_t *out_chunk_offset, size_t *out_chunk_size) {
    return find_chunk(streamFile, chunk_id, start_offset, full_chunk_size, out_chunk_offset, out_chunk_size, 0, 0);
}
Пример #29
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;
}