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"); }
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; }
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; }