예제 #1
0
void CacheList::locate(CacheItem *i, int local_only)
{
//  dprintf("cache in %s, type %d, offset %d\n",crc_manager.get_filename(i->file_number),i->type,i->offset);
  if (i->file_number!=last_file)
  {
    if (fp) delete fp;
    if (last_dir) delete last_dir;
    if (local_only)
      fp=new jFILE(crc_manager.get_filename(i->file_number),"rb");
    else
      fp=open_file(crc_manager.get_filename(i->file_number),"rb");


    if (fp->open_failure())
    {
      printf("Ooch. Could not open file %s\n",crc_manager.get_filename(i->file_number));
      delete fp;
      exit(0);
    }

    last_offset=-1;
    last_dir=new spec_directory(fp);
    last_file=i->file_number;
  }
  if (i->offset!=last_offset)
  {
    fp->seek(i->offset,SEEK_SET);
    last_offset=i->offset;
  }
  used=1;
}
예제 #2
0
int CacheList::prof_size() {
	int size = 0; // count up the size for a spec enrty
	size += 2; // total filenames
	int i;
	for (i = 0; i < crc_manager.total_filenames(); i++)
		size += strlen(crc_manager.get_filename(i)) + 2; // filename + 0 + size of string

	size += 4; // number of entries saved

	for (i = 0; i < total; i++)
		if (list[i].last_access > 0) // don't save unaccessed counts
			size += 2 + 4 + 1; // filenumber & offset & type

	return size;
}
예제 #3
0
void CacheList::show_accessed()
{
  int old=last_access,new_old_accessed;
  CacheItem *ci,*new_old;

  do
  {
    new_old_accessed=-1;
    new_old=NULL;
    ci=list;
    for (int i=0; i<total; i++,ci++)
    {
      if (ci->last_access<old && ci->last_access>0 && ci->last_access>new_old_accessed)
      {
    new_old_accessed=ci->last_access;
        new_old=ci;
      }
    }
    if (new_old)
    {
      ci=new_old;
      old=ci->last_access;
      printf("type=(%20s) file=(%20s) access=(%6ld)\n",spec_types[ci->type],
         crc_manager.get_filename(ci->file_number),
         (long int)ci->last_access);
    }
  } while (new_old);
}
예제 #4
0
void CacheList::prof_write(bFILE *fp)
{
  if (prof_data)
  {
    int *ordered_ids=(int *)malloc(sizeof(int)*total);
    int i;
    for (i=0; i<total; i++) ordered_ids[i]=i;
    qsort(ordered_ids,total,sizeof(int),c_sorter);

    if (fp)
    {
      fp->write_uint16(crc_manager.total_filenames());
      for (i=0; i<crc_manager.total_filenames(); i++)
      {
    int l=strlen(crc_manager.get_filename(i))+1;
        fp->write_uint8(l);
    fp->write(crc_manager.get_filename(i),l);
      }

      int tsaved=0;
      for (i=0; i<total; i++)
        if (list[i].last_access>0) tsaved++;
      fp->write_uint32(tsaved);

      for (i=0; i<total; i++)
      {
    int id=ordered_ids[i];
        if (list[id].last_access>0)       // don't save unaccessed counts
    {
      fp->write_uint8(list[id].type);    // save type, if type changed on reload
                                        // don't cache in-> its a different refrence
      fp->write_uint16(list[id].file_number);
      fp->write_uint32(list[id].offset);
    }
      }
    }

    free(ordered_ids);

  } else dprintf("Cache profiling was not initialized\n");
}
예제 #5
0
sound_effect *CacheList::sfx(int id) {
	CacheItem *me = list + id;
	CONDITION(id<total && id>=0 && me->file_number>=0, "Bad id");
	if (me->last_access >= 0) {
		touch(me);
		// hold me, feel me, be me!
		return (sound_effect *) me->data;
	} else {
		touch(me);
		// hold me, feel me, be me!
		char *fn = crc_manager.get_filename(me->file_number);
		me->data = (void *) new sound_effect(fn);
		return (sound_effect *) me->data;
	}
}
예제 #6
0
int CacheList::reg(char const *filename, char const *name, int type, int rm_dups)
{
    int fn = crc_manager.get_filenumber(filename);
    int offset = 0;

    if (type == SPEC_EXTERN_SFX)
    {
    	// Missing sound effect is not a critical error, so we don't
    	// quit when error happens.
        bFILE *check = open_file(filename, "rb");
        if (!check->open_failure())
        {
        	printf("Unable to open sfx file '%s' for reading, ignoring.\n", filename);
        }
        delete check;
    }
    else
    {
        // If a classic spec item, look for it in the archive.
        spec_directory *sd = sd_cache.get_spec_directory(filename);

        if (!sd)
        {
            printf("Unable to open file %s for item %s\n", filename, name);
            assert(false);
            exit(0);
        }

        spec_entry *se = NULL;
        if (type != -1)
            se = sd->find(name, type);
        if (!se)
            se = sd->find(name);
        if (!se)
        {
            printf("No such item %s in file %s\n", name, filename);
            assert(false);
            exit(0);
        }

        if (type >= 0 && type != se->type &&
             ((type != SPEC_CHARACTER2 && type != SPEC_CHARACTER)
               || (se->type != SPEC_CHARACTER && se->type != SPEC_CHARACTER2)))
        {
            printf("Item %s of file %s should be type %s\n",
                   name, filename, spec_types[type]);
            assert(false);
            exit(0);
        }

        type = se->type;
        offset = se->offset;
    }

    // Check whether there is another entry pointing to the same
    // file and offset, and return it as a shortcut.
    if (rm_dups)
    {
        for (int i = 0; i < total; i++)
            if (list[i].file_number == fn && list[i].offset == offset)
                return i;
    }

    int id = AllocId();

    CHECK(id < total && list[id].file_number < 0);

    list[id].file_number = fn;
    list[id].last_access = -1;
    list[id].data = NULL;
    list[id].offset = offset;
    list[id].type = type;

    return id;
}
예제 #7
0
void CacheList::load_cache_prof_info(char *filename, level *lev)
{
  int j;
  for (j=0; j<this->total; j++)
    if (list[j].last_access>=0)      // reset all loaded cache items to 0, all non-load to -1
      list[j].last_access=0;

  preload_cache(lev);                // preliminary guesses at stuff to load

  int load_fail=1;
  bFILE *fp=open_file(filename,"rb");
  if (!fp->open_failure())
  {
    spec_directory sd(fp);
    spec_entry *se=sd.find("cache profile info");   // see if the cache profile info is in the file
    if (se)
    {
      fp->seek(se->offset,0);

      char name[255];
      int tnames=0;
      int *fnum_remap;    // remaps old filenumbers into current ones

      tnames=fp->read_uint16();
      if (tnames)                     /// make sure there isn't bad info in the file
      {
    fnum_remap=(int *)malloc(sizeof(int)*tnames);

    int i;
    for (i=0; i<tnames; i++)
    {
      fp->read(name,fp->read_uint8());
      fnum_remap[i]=-1;                    // initialize the map to no-map

      int j;
      for (j=0; j<crc_manager.total_filenames(); j++)
        if (!strcmp(crc_manager.get_filename(j),name))
          fnum_remap[i]=j;
    }

    int tsaved = fp->read_uint32();


    int *priority=(int *)malloc(tsaved*sizeof(int));
    memset(priority,0xff,tsaved*sizeof(int));   // initialize to -1
    int tmatches=0;

    sorted_id_list=(int *)malloc(sizeof(int)*total);
    for (j=0; j<total; j++) sorted_id_list[j]=j;
    qsort(sorted_id_list,total,sizeof(int),s_offset_compare);

    for (i=0; i<tsaved; i++)
    {
      fp->read_uint8(); // read type
      short file_num=fp->read_uint16();
      if (file_num>=tnames)  // bad data?
        file_num=-1;
      else file_num=fnum_remap[file_num];

      uint32_t offset=fp->read_uint32();

      // search for a match
      j=search(sorted_id_list,file_num,offset);
      if (j!=-1)
      {
        if (list[j].last_access<0)  // if not loaded
          list[j].last_access=-2;      // mark as needing loading
        else list[j].last_access=2;   // mark as loaded and needing to stay that way
        priority[i]=j;
        tmatches++;
      }
    }

    free(sorted_id_list);            // was used for searching, no longer needed

    for (j=0; j<total; j++)
      if (list[j].last_access==0)
        unmalloc(list+j);             // free any cache entries that are not accessed at all in the level


    ful=0;
    int tcached=0;
    for (j=0; j<total; j++)    // now load all of the objects until full
    {
//      stat_man->update(j*70/total+25);
      if (list[j].file_number>=0 && list[j].last_access==-2)
      {
        list[j].last_access=-1;
        if (!ful)
        {
          switch (list[j].type)
          {
        case SPEC_BACKTILE : backt(j); break;
        case SPEC_FORETILE : foret(j); break;
        case SPEC_CHARACTER :
        case SPEC_CHARACTER2 : fig(j); break;
        case SPEC_IMAGE : img(j); break;
        case SPEC_PARTICLE : part(j); break;
        case SPEC_EXTERN_SFX : sfx(j); break;
        case SPEC_EXTERNAL_LCACHE : lblock(j); break;
        case SPEC_PALETTE : ctint(j); break;
          }
          tcached++;
        }
      }
    }
    load_fail=0;
//    if (full())
//      dprintf("Cache filled while loading\n");

    if (tsaved>tmatches)
      tmatches=tsaved+1;

    last_access=tmatches+1;
    for (i=0; i<tsaved; i++)      // reorder the last access of each cache to reflect prioirties
    {
      if (priority[i]!=-1)
      {
        if (list[priority[i]].last_access!=-1)            // make sure this wasn't the last item
          list[priority[i]].last_access=tmatches--;
      }
    }

    free(priority);
    free(fnum_remap);


      }
    }
  }

  if (load_fail) // no cache file, go solely on above gueses
  {
    int j;
    for (j=0; j<total; j++)    // now load all of the objects until full, don't free old stuff
    {
//      stat_man->update(j*70/total+25);

      if (list[j].file_number>=0 && list[j].last_access==-2)
      {
    list[j].last_access=-1;
    if (!ful)
    {
      switch (list[j].type)
      {
        case SPEC_BACKTILE : backt(j); break;
        case SPEC_FORETILE : foret(j); break;
        case SPEC_CHARACTER :
        case SPEC_CHARACTER2 : fig(j); break;
        case SPEC_IMAGE : img(j); break;
        case SPEC_PARTICLE : part(j); break;
        case SPEC_EXTERN_SFX : sfx(j); break;
        case SPEC_EXTERNAL_LCACHE : lblock(j); break;
        case SPEC_PALETTE : ctint(j); break;
      }
    }
      }
    }
    if (full())
      dprintf("Cache filled while loading\n");
  }
  delete fp;
}
예제 #8
0
int crc_man_write_crc_file(char const *filename)
{
  return crc_manager.write_crc_file(filename);
}
예제 #9
0
int CacheList::reg(char const *filename, char const *name, int type,
		int rm_dups) {
	int fn = crc_manager.get_filenumber(filename);
	int offset = 0;

	if (type == SPEC_EXTERN_SFX) {
		// If an extern sound effect then just make sure it's there. If sound
		// is disabled, ignore the load error, just pretend it's all OK.
		bFILE *check = open_file(filename, "rb");
		if (!check->open_failure()) {
			char buf[4];
			check->read(buf, 4);
			if (memcmp(buf, "RIFF", 4)) {
				printf("File %s is not a WAV file\n", filename);
				exit(0);
			}
		} else if (sound_avail) {
			printf("Unable to open file '%s' for reading\n", filename);
			exit(0);
		}
		delete check;
	} else {
		// If a classic spec item, look for it in the archive.
		spec_directory *sd = sd_cache.get_spec_directory(filename);

		if (!sd) {
			printf("Unable to open file %s for item %s\n", filename, name);
			exit(0);
		}

		spec_entry *se = NULL;
		if (type != -1)
			se = sd->find(name, type);
		if (!se)
			se = sd->find(name);
		if (!se) {
			printf("No such item %s in file %s\n", name, filename);
			exit(0);
		}

		if (type >= 0 && type != se->type
				&& ((type != SPEC_CHARACTER2 && type != SPEC_CHARACTER)
						|| (se->type != SPEC_CHARACTER
								&& se->type != SPEC_CHARACTER2))) {
			printf("Item %s of file %s should be type %s\n", name, filename,
					spec_types[type]);
			exit(0);
		}

		type = se->type;
		offset = se->offset;
	}

	// Check whether there is another entry pointing to the same
	// file and offset, and return it as a shortcut.
	if (rm_dups) {
		for (int i = 0; i < total; i++)
			if (list[i].file_number == fn && list[i].offset == offset)
				return i;
	}

	int id = AllocId();

	CHECK(id < total && list[id].file_number < 0);

	list[id].file_number = fn;
	list[id].last_access = -1;
	list[id].data = NULL;
	list[id].offset = offset;
	list[id].type = type;

	return id;
}